├── .gitignore ├── README.md ├── app ├── .gitignore ├── build.gradle ├── lzy.keystore ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── lzy │ │ └── fastdevelop │ │ ├── MainActivity.java │ │ └── MyApplication.java │ └── res │ ├── drawable-v24 │ └── ic_launcher_foreground.xml │ ├── drawable │ └── ic_launcher_background.xml │ ├── layout │ └── activity_main.xml │ ├── mipmap-anydpi-v26 │ ├── ic_launcher.xml │ └── ic_launcher_round.xml │ ├── mipmap-hdpi │ ├── ic_launcher.png │ └── ic_launcher_round.png │ ├── mipmap-mdpi │ ├── ic_launcher.png │ └── ic_launcher_round.png │ ├── mipmap-xhdpi │ ├── ic_launcher.png │ └── ic_launcher_round.png │ ├── mipmap-xxhdpi │ ├── ic_dog.gif │ ├── ic_launcher.png │ └── ic_launcher_round.png │ ├── mipmap-xxxhdpi │ ├── ic_launcher.png │ └── ic_launcher_round.png │ └── values │ ├── colors.xml │ ├── strings.xml │ └── styles.xml ├── bizCore ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── lzy │ │ └── bizcore │ │ ├── AppConfig.java │ │ ├── file │ │ └── FolderManager.java │ │ ├── helper │ │ └── NotifiManager.java │ │ └── webview │ │ ├── WebViewFragment.java │ │ ├── WebViewHelper.java │ │ └── WebViewJsInject.java │ └── res │ ├── layout │ ├── biz_core_custom_notification_item_layout.xml │ └── biz_core_fragment_webview.xml │ ├── mipmap-xxhdpi │ ├── biz_core_icon_large.png │ ├── biz_core_icon_small.png │ └── biz_core_icon_small_alpha.png │ └── values │ ├── ids.xml │ └── strings.xml ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── libBaseFun ├── .gitignore ├── build.gradle ├── consumer-rules.pro ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── lzy │ │ └── libbasefun │ │ └── ExampleInstrumentedTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── lzy │ │ │ └── libbasefun │ │ │ ├── glide │ │ │ ├── module │ │ │ │ ├── MyAppGlideModule.java │ │ │ │ └── OkHttpLibraryGlideModule.java │ │ │ └── recyclerview │ │ │ │ └── MyPreloadModelProvider.java │ │ │ ├── lru │ │ │ └── DiskLruCacheMgr.java │ │ │ └── rxjava │ │ │ └── RxUtils.java │ └── res │ │ └── values │ │ └── strings.xml │ └── test │ └── java │ └── com │ └── lzy │ └── libbasefun │ └── ExampleUnitTest.java ├── libFileProvider ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── lzy │ │ └── libfileprovider │ │ ├── FileProviderUtil.java │ │ └── LibFileProvider.java │ └── res │ ├── values │ └── strings.xml │ └── xml │ └── lib_fileprovider_file_paths.xml ├── libHttp ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── lzy │ │ └── libhttp │ │ ├── HttpConstants.java │ │ ├── MyOkHttpClient.java │ │ ├── RetrofitBuildHelper.java │ │ ├── interceptor │ │ └── LogInterceptor.java │ │ └── result │ │ └── BaseResult.java │ └── res │ └── values │ └── strings.xml ├── libUtils ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── lzy │ │ └── utils │ │ ├── CommonExecuter.java │ │ ├── DisplayUtil.java │ │ ├── IntentUtil.java │ │ ├── JsonUtil.java │ │ ├── ListUtil.java │ │ ├── SharedPreferencesUtil.java │ │ ├── SoftInputManager.java │ │ ├── StringUtil.java │ │ ├── SystemActivityUtil.java │ │ ├── TimeUtil.java │ │ ├── encrypt │ │ └── MD5Util.java │ │ ├── file │ │ └── FileUtil.java │ │ ├── log │ │ └── MLog.java │ │ ├── network │ │ └── NetWorkUtil.java │ │ ├── statusbar │ │ └── StatusBarUtil.java │ │ ├── system │ │ ├── ClipboardUtil.java │ │ ├── DeviceUtil.java │ │ └── ScreenUtil.java │ │ └── url │ │ ├── UrlEncode.java │ │ └── UrlHelper.java │ └── res │ └── values │ ├── ids.xml │ └── strings.xml ├── libView ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── lzy │ │ └── libview │ │ ├── activity │ │ ├── BaseActivity.java │ │ ├── BaseFragmentActivity.java │ │ ├── BaseTitleFragmentActivity.java │ │ ├── IClickRightButtonAble.java │ │ ├── IListBacktop.java │ │ └── IOnKeyDownEvent.java │ │ ├── custom │ │ └── ResizeLayout.java │ │ ├── dialog │ │ ├── BaseDialogFragment.java │ │ ├── CustomAskDialog.java │ │ └── CustomWaitingDialog.java │ │ ├── fragment │ │ └── BaseFragment.java │ │ ├── mvp │ │ ├── AbstractBasePresenter.java │ │ ├── IBasePresenter.java │ │ └── IBaseView.java │ │ └── permission │ │ └── OnPermissionListener.java │ └── res │ ├── anim │ └── lib_view_anim_none.xml │ ├── drawable │ ├── lib_view_btn_empty_tip.xml │ ├── lib_view_btn_empty_tip_nor.xml │ ├── lib_view_btn_empty_tip_sel.xml │ ├── lib_view_dlg_ask_bg.xml │ ├── lib_view_dlg_progress_bar.xml │ ├── lib_view_ripple_bg.xml │ └── lib_view_webview_progressbar_style.xml │ ├── layout │ ├── lib_view_activity_base.xml │ ├── lib_view_activity_base_title.xml │ ├── lib_view_ask_dlg.xml │ ├── lib_view_cancel_ok_btns.xml │ ├── lib_view_layout_empty_tips.xml │ └── lib_view_progress_dialog_layout.xml │ ├── mipmap-xxhdpi │ ├── ic_menu_more_overflow.png │ ├── lib_view_back.png │ ├── lib_view_dlg_progress.png │ └── lib_view_icon_network_error.png │ └── values │ ├── colors.xml │ ├── dimens.xml │ ├── strings.xml │ └── styles.xml ├── markets.txt └── 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 | secring.gpg 11 | gradle.properties 12 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # FastDevelop 2 | Android项目快速开发框架 3 | 一、包含以下功能 4 | 1、工具类 5 | 2、基础Activity、Fragment、Dialog 6 | 3、基础mvp和组件化框架 7 | 4、运行时权限库 8 | 5、核心业务库 9 | 6、网络库 10 | 7、图片加载库 11 | 12 | 二、 13 | 1、运行时权限引用和封装EasyPermission 14 | 2、图片加载库使用Glide 15 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | apply plugin: 'packer' 3 | 4 | android { 5 | compileSdkVersion rootProject.ext.compileSdkVersion 6 | 7 | signingConfigs { 8 | default_sign { 9 | keyAlias 'fastdevelop' 10 | keyPassword 'lzyang' 11 | storeFile file('lzy.keystore') 12 | storePassword 'lzyang' 13 | v2SigningEnabled true 14 | } 15 | } 16 | 17 | defaultConfig { 18 | applicationId "com.lzy.fastdevelop" 19 | minSdkVersion rootProject.ext.minSdkVersion 20 | targetSdkVersion rootProject.ext.targetSdkVersion 21 | versionCode rootProject.ext.versionCode 22 | versionName rootProject.ext.versionName 23 | ndk { 24 | abiFilters 'armeabi' 25 | } 26 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 27 | } 28 | 29 | dexOptions { 30 | javaMaxHeapSize "4g" 31 | } 32 | 33 | lintOptions { 34 | checkReleaseBuilds false 35 | // Or, if you prefer, you can continue to check for errors in release builds, 36 | // but continue the build even when errors are found: 37 | abortOnError false 38 | } 39 | 40 | buildTypes { 41 | debug { 42 | debuggable true 43 | minifyEnabled false 44 | signingConfig signingConfigs.default_sign 45 | } 46 | release { 47 | signingConfig signingConfigs.default_sign 48 | debuggable false 49 | //启用资源压缩 50 | shrinkResources true 51 | zipAlignEnabled true 52 | minifyEnabled true 53 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 54 | } 55 | } 56 | 57 | packer { 58 | //指定最终输出的渠道包文件名的格式模版 59 | archiveNameFormat = '${projectName}-${channel}-${buildType}-${versionCode}' 60 | //指定最终输出的渠道包的存储位置 61 | archiveOutput = new File(project.rootProject.buildDir, "apks") 62 | channelFile = new File(project.rootDir, "markets.txt") 63 | } 64 | 65 | } 66 | 67 | dependencies { 68 | implementation fileTree(include: ['*.jar'], dir: 'libs') 69 | implementation project(':bizCore') 70 | implementation 'com.mcxiaoke.packer-ng:helper:2.0.1' 71 | } 72 | -------------------------------------------------------------------------------- /app/lzy.keystore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lzyang187/FastDevelop/86dc57026a8b4e9b193891edbecb6ee594de157a/app/lzy.keystore -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | 23 | #-------- common setting --------# 24 | -keepclassmembers class fqcn.of.javascript.interface.for.webview { 25 | public *; 26 | } 27 | -optimizations !code/simplification/arithmetic,!code/simplification/cast,!field/*,!class/merging/* 28 | # 设置混淆的压缩比率 0 ~ 7 29 | -optimizationpasses 5 30 | -allowaccessmodification 31 | #不做预校验的操作 32 | -dontpreverify 33 | 34 | # The remainder of this file is identical to the non-optimized version 35 | # of the Proguard configuration file (except that the other file has 36 | # flags to turn off optimization). 37 | #包名不混合大小写 38 | -dontusemixedcaseclassnames 39 | -dontskipnonpubliclibraryclasses 40 | -dontskipnonpubliclibraryclassmembers 41 | -verbose 42 | 43 | -keepattributes *Annotation* 44 | -keepattributes *JavascriptInterface* 45 | -keep public class com.google.vending.licensing.ILicensingService 46 | -keep public class com.android.vending.licensing.ILicensingService 47 | 48 | # For native methods, see http://proguard.sourceforge.net/manual/examples.html#native 49 | -keepclasseswithmembernames class * { 50 | native ; 51 | } 52 | 53 | # keep setters in Views so that animations can still work. 54 | # see http://proguard.sourceforge.net/manual/examples.html#beans 55 | -keepclassmembers public class * extends android.view.View { 56 | void set*(***); 57 | *** get*(); 58 | } 59 | 60 | # We want to keep methods in Activity that could be used in the XML attribute onClick 61 | -keepclassmembers class * extends android.app.Activity { 62 | public void *(android.view.View); 63 | } 64 | 65 | # For enumeration classes, see http://proguard.sourceforge.net/manual/examples.html#enumerations 66 | -keepclassmembers enum * { 67 | public static **[] values(); 68 | public static ** valueOf(java.lang.String); 69 | } 70 | 71 | #保持Parcelable接口不被混淆 72 | -keep class * implements android.os.Parcelable { 73 | public static final android.os.Parcelable$Creator *; 74 | } 75 | 76 | -keepclassmembers class **.R$* { 77 | public static ; 78 | } 79 | 80 | # The support library contains references to newer platform versions. 81 | # Don't warn about those in case this app is linking against an older 82 | # platform version. We know about them, and they are safe. 83 | -dontwarn android.support.** 84 | -keep class android.support.v4.** { *; } 85 | -keep interface android.support.v4.app.** { *; } 86 | -keep public class * extends android.support.v4.** 87 | -keep public class * extends android.app.Fragment 88 | 89 | -keep class android.support.v7.** { *; } 90 | -keep interface android.support.v7.app.** { *; } 91 | -keep public class * extends android.support.v7.** 92 | 93 | -keep public class * extends android.app.Fragment 94 | -keep public class * extends android.app.Activity 95 | -keep public class * extends android.app.Application 96 | -keep public class * extends android.app.Service 97 | -keep public class * extends android.content.BroadcastReceiver 98 | -keep public class * extends android.content.ContentProvider 99 | -keep public class * extends android.app.backup.BackupAgentHelper 100 | -keep public class * extends android.preference.Preference 101 | -keep public class com.android.vending.licensing.ILicensingService 102 | 103 | -keepclassmembers class ** { 104 | public void onEvent*(**); 105 | void onEvent*(**); 106 | } 107 | 108 | -keep class * extends java.io.InputStream {*;} 109 | -keep class * implements java.io.Serializable {*;} 110 | 111 | #保留代码行号,方便异常信息的追踪 112 | -renamesourcefileattribute SourceFile 113 | -keepattributes SourceFile,LineNumberTable 114 | 115 | #保持自定义控件类不被混淆 116 | -keepclasseswithmembers class * { 117 | public (android.content.Context, android.util.AttributeSet); 118 | } 119 | -keepclasseswithmembers class * { 120 | public (android.content.Context, android.util.AttributeSet, int); 121 | } 122 | -keepclassmembers class * extends android.app.Activity { 123 | public void *(android.view.View); 124 | } 125 | 126 | #保持 Serializable 不被混淆并且enum 类也不被混淆 127 | -keepclassmembers class * implements java.io.Serializable { 128 | static final long serialVersionUID; 129 | private static final java.io.ObjectStreamField[] serialPersistentFields; 130 | !static !transient ; 131 | !private ; 132 | !private ; 133 | private void writeObject(java.io.ObjectOutputStream); 134 | private void readObject(java.io.ObjectInputStream); 135 | java.lang.Object writeReplace(); 136 | java.lang.Object readResolve(); 137 | } 138 | 139 | -keepclassmembers class * { 140 | public void *ButtonClicked(android.view.View); 141 | } 142 | 143 | #-------- project setting --------# 144 | -keeppackagenames com.lzy.** 145 | -keep public class com.lzy.fastdevelop.R$*{public static final int *;} 146 | 147 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /app/src/main/java/com/lzy/fastdevelop/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.lzy.fastdevelop; 2 | 3 | import android.Manifest; 4 | import android.app.PendingIntent; 5 | import android.content.Intent; 6 | import android.os.Bundle; 7 | import android.util.Log; 8 | import android.widget.ImageView; 9 | 10 | import com.bumptech.glide.Glide; 11 | import com.bumptech.glide.load.MultiTransformation; 12 | import com.bumptech.glide.request.RequestOptions; 13 | import com.lzy.bizcore.helper.NotifiManager; 14 | import com.lzy.bizcore.webview.WebViewFragment; 15 | import com.lzy.libview.activity.BaseActivity; 16 | import com.lzy.libview.activity.BaseFragmentActivity; 17 | import com.lzy.libview.activity.BaseTitleFragmentActivity; 18 | import com.lzy.libview.dialog.CustomAskDialog; 19 | import com.lzy.libview.permission.OnPermissionListener; 20 | import com.lzy.utils.ListUtil; 21 | import com.lzy.utils.statusbar.StatusBarUtil; 22 | import com.orhanobut.logger.AndroidLogAdapter; 23 | import com.orhanobut.logger.DiskLogAdapter; 24 | import com.orhanobut.logger.FormatStrategy; 25 | import com.orhanobut.logger.Logger; 26 | import com.orhanobut.logger.PrettyFormatStrategy; 27 | 28 | import java.util.Arrays; 29 | import java.util.HashMap; 30 | import java.util.List; 31 | import java.util.Map; 32 | 33 | import jp.wasabeef.glide.transformations.BlurTransformation; 34 | import jp.wasabeef.glide.transformations.GrayscaleTransformation; 35 | import pub.devrel.easypermissions.EasyPermissions; 36 | 37 | public class MainActivity extends BaseActivity implements OnPermissionListener { 38 | 39 | private static final int REQUEST_CODE = 10; 40 | 41 | @Override 42 | protected void onCreate(Bundle savedInstanceState) { 43 | super.onCreate(savedInstanceState); 44 | StatusBarUtil.transparentStatus(this); 45 | setContentView(R.layout.activity_main); 46 | 47 | checkAndRequestPermissions("不授予权限,功能无法使用哦", REQUEST_CODE, this, Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE); 48 | 49 | Intent intent = new Intent(this, BaseTitleFragmentActivity.class); 50 | intent.putExtra(BaseFragmentActivity.KEY_FRAGMENT_CLASS_NAME, WebViewFragment.class.getName()); 51 | intent.putExtra(WebViewFragment.KEY_WEB_VIEW_URL, "https://www.baidu.com/"); 52 | NotifiManager.startNotify(this, "我是标题", "我是内容", PendingIntent.getActivity(this, 100, intent, PendingIntent.FLAG_CANCEL_CURRENT)); 53 | 54 | CustomAskDialog dialog = new CustomAskDialog("标题", "内容"); 55 | dialog.show(getSupportFragmentManager(), "ask"); 56 | 57 | ImageView iv = findViewById(R.id.imageview); 58 | Glide.with(this) 59 | .load("https://www.wanandroid.com/blogimgs/90c6cc12-742e-4c9f-b318-b912f163b8d0.png") 60 | .apply(RequestOptions.bitmapTransform(new MultiTransformation<>(new BlurTransformation(25, 5), new GrayscaleTransformation()))) 61 | .into(iv); 62 | 63 | Log.d("Tag", "I'm a log which you don't see easily, hehe"); 64 | Log.d("json content", "{ \"key\": 3, \n \"value\": something}"); 65 | Log.d("error", "There is a crash somewhere or any warning"); 66 | 67 | Logger.addLogAdapter(new AndroidLogAdapter()); 68 | Logger.d("message"); 69 | 70 | Logger.clearLogAdapters(); 71 | 72 | 73 | FormatStrategy formatStrategy = PrettyFormatStrategy.newBuilder() 74 | .showThreadInfo(false) // (Optional) Whether to show thread info or not. Default true 75 | .methodCount(0) // (Optional) How many method line to show. Default 2 76 | .methodOffset(3) // (Optional) Skips some method invokes in stack trace. Default 5 77 | // .logStrategy(customLog) // (Optional) Changes the log strategy to print out. Default LogCat 78 | .tag("My custom tag") // (Optional) Custom tag for each log. Default PRETTY_LOGGER 79 | .build(); 80 | 81 | Logger.addLogAdapter(new AndroidLogAdapter(formatStrategy)); 82 | 83 | Logger.addLogAdapter(new AndroidLogAdapter() { 84 | @Override public boolean isLoggable(int priority, String tag) { 85 | return BuildConfig.DEBUG; 86 | } 87 | }); 88 | 89 | Logger.addLogAdapter(new DiskLogAdapter()); 90 | 91 | 92 | Logger.w("no thread info and only 1 method"); 93 | 94 | Logger.clearLogAdapters(); 95 | formatStrategy = PrettyFormatStrategy.newBuilder() 96 | .showThreadInfo(false) 97 | .methodCount(0) 98 | .build(); 99 | 100 | Logger.addLogAdapter(new AndroidLogAdapter(formatStrategy)); 101 | Logger.i("no thread info and method info"); 102 | 103 | Logger.t("tag").e("Custom tag for only one use"); 104 | 105 | Logger.json("{ \"key\": 3, \"value\": something}"); 106 | 107 | Logger.d(Arrays.asList("foo", "bar")); 108 | 109 | Map map = new HashMap<>(); 110 | map.put("key", "value"); 111 | map.put("key1", "value2"); 112 | 113 | Logger.d(map); 114 | 115 | Logger.clearLogAdapters(); 116 | formatStrategy = PrettyFormatStrategy.newBuilder() 117 | .showThreadInfo(false) 118 | .methodCount(0) 119 | .tag("MyTag") 120 | .build(); 121 | Logger.addLogAdapter(new AndroidLogAdapter(formatStrategy)); 122 | 123 | Logger.w("my log message with my tag"); 124 | 125 | 126 | } 127 | 128 | @Override 129 | public void onPermGranted(int requestCode, List perms) { 130 | if (requestCode == REQUEST_CODE) { 131 | if (ListUtil.isNotEmpty(perms) && 132 | perms.contains(Manifest.permission.READ_EXTERNAL_STORAGE)) { 133 | Logger.d("读sd卡权限已获取"); 134 | } 135 | if (ListUtil.isNotEmpty(perms) && 136 | perms.contains(Manifest.permission.WRITE_EXTERNAL_STORAGE)) { 137 | Logger.d("写sd卡权限已获取"); 138 | } 139 | } 140 | } 141 | 142 | @Override 143 | public void onPermDenied(int requestCode, List perms) { 144 | if (requestCode == REQUEST_CODE) { 145 | if (ListUtil.isNotEmpty(perms) && 146 | perms.contains(Manifest.permission.READ_EXTERNAL_STORAGE)) { 147 | Logger.d("读sd卡权限已拒绝"); 148 | } 149 | if (ListUtil.isNotEmpty(perms) && 150 | perms.contains(Manifest.permission.WRITE_EXTERNAL_STORAGE)) { 151 | Logger.d("写sd卡权限已拒绝"); 152 | } 153 | } 154 | if (!gotoSettingActivity(perms, getString(R.string.lib_view_rationale_settings_dialog))) { 155 | Logger.d("用户没有选中不再提示"); 156 | } 157 | } 158 | 159 | @Override 160 | public void onPermSystemSettingResult(int requestCode) { 161 | if (requestCode == REQUEST_CODE) { 162 | if (EasyPermissions.hasPermissions(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)) { 163 | Logger.d("写sd卡权限已在系统设置页面获取"); 164 | } else { 165 | Logger.d("写sd卡权限已在系统设置页面被拒绝"); 166 | } 167 | } 168 | } 169 | 170 | } 171 | -------------------------------------------------------------------------------- /app/src/main/java/com/lzy/fastdevelop/MyApplication.java: -------------------------------------------------------------------------------- 1 | package com.lzy.fastdevelop; 2 | 3 | import android.app.Application; 4 | 5 | import com.lzy.bizcore.AppConfig; 6 | import com.lzy.libbasefun.lru.DiskLruCacheMgr; 7 | import com.lzy.libhttp.MyOkHttpClient; 8 | import com.lzy.utils.StringUtil; 9 | import com.lzy.utils.log.MLog; 10 | import com.mcxiaoke.packer.helper.PackerNg; 11 | 12 | import java.io.File; 13 | 14 | /** 15 | * 应用的Application 16 | * 17 | * @author: cyli8 18 | * @date: 2018/2/27 15:34 19 | */ 20 | 21 | public class MyApplication extends Application { 22 | 23 | @Override 24 | public void onCreate() { 25 | super.onCreate(); 26 | String channel = PackerNg.getChannel(this); 27 | if (StringUtil.isEmpty(channel)) { 28 | channel = getString(R.string.official_channel); 29 | } 30 | AppConfig.init(this, BuildConfig.DEBUG, BuildConfig.VERSION_CODE, BuildConfig.VERSION_NAME, 31 | getString(R.string.app_name), BuildConfig.APPLICATION_ID, channel); 32 | // MLog.initLogger(AppConfig.APP_NAME, BuildConfig.DEBUG); 33 | MyOkHttpClient.setCacheFile(new File(getExternalCacheDir(), "http")); 34 | DiskLruCacheMgr.getInstance().init(this); 35 | } 36 | } 37 | 38 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-v24/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 7 | 12 | 13 | 19 | 22 | 25 | 26 | 27 | 28 | 34 | 35 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 10 | 15 | 20 | 25 | 30 | 35 | 40 | 45 | 50 | 55 | 60 | 65 | 70 | 75 | 80 | 85 | 90 | 95 | 100 | 105 | 110 | 115 | 120 | 125 | 130 | 135 | 140 | 145 | 150 | 155 | 160 | 165 | 170 | 171 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lzyang187/FastDevelop/86dc57026a8b4e9b193891edbecb6ee594de157a/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lzyang187/FastDevelop/86dc57026a8b4e9b193891edbecb6ee594de157a/app/src/main/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lzyang187/FastDevelop/86dc57026a8b4e9b193891edbecb6ee594de157a/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lzyang187/FastDevelop/86dc57026a8b4e9b193891edbecb6ee594de157a/app/src/main/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lzyang187/FastDevelop/86dc57026a8b4e9b193891edbecb6ee594de157a/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lzyang187/FastDevelop/86dc57026a8b4e9b193891edbecb6ee594de157a/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_dog.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lzyang187/FastDevelop/86dc57026a8b4e9b193891edbecb6ee594de157a/app/src/main/res/mipmap-xxhdpi/ic_dog.gif -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lzyang187/FastDevelop/86dc57026a8b4e9b193891edbecb6ee594de157a/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lzyang187/FastDevelop/86dc57026a8b4e9b193891edbecb6ee594de157a/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lzyang187/FastDevelop/86dc57026a8b4e9b193891edbecb6ee594de157a/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lzyang187/FastDevelop/86dc57026a8b4e9b193891edbecb6ee594de157a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #3F51B5 4 | #303F9F 5 | #FF4081 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | FastDevelop 3 | 701 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /bizCore/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /bizCore/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | 3 | android { 4 | compileSdkVersion rootProject.ext.compileSdkVersion 5 | 6 | 7 | defaultConfig { 8 | minSdkVersion rootProject.ext.minSdkVersion 9 | targetSdkVersion rootProject.ext.targetSdkVersion 10 | versionCode 1 11 | versionName "1.0" 12 | 13 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 14 | 15 | } 16 | 17 | buildTypes { 18 | release { 19 | minifyEnabled true 20 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 21 | } 22 | } 23 | 24 | resourcePrefix "biz_core_" 25 | 26 | } 27 | 28 | dependencies { 29 | implementation fileTree(include: ['*.jar'], dir: 'libs') 30 | api project(':libView') 31 | api project(':libHttp') 32 | api project(':libFileProvider') 33 | api project(':libBaseFun') 34 | api project(':libUtils') 35 | } 36 | 37 | buildscript { 38 | repositories { 39 | mavenCentral() 40 | } 41 | dependencies { 42 | classpath 'com.vanniktech:gradle-maven-publish-plugin:0.17.0' 43 | } 44 | } 45 | 46 | allprojects { 47 | plugins.withId("com.vanniktech.maven.publish") { 48 | mavenPublish { 49 | sonatypeHost = "S01" 50 | } 51 | } 52 | tasks.withType(Javadoc) { 53 | options.addStringOption('Xdoclint:none', '-quiet') //忽略javadoc错误 54 | options { 55 | encoding "UTF-8" 56 | charSet 'UTF-8' 57 | links "http://docs.oracle.com/javase/7/docs/api" 58 | } 59 | } 60 | } 61 | 62 | apply plugin: "com.vanniktech.maven.publish" -------------------------------------------------------------------------------- /bizCore/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | 23 | # Fresco 24 | -keep class com.facebook.fresco.** {*;} 25 | -keep interface com.facebook.fresco.** {*;} 26 | -keep enum com.facebook.fresco.** {*;} -------------------------------------------------------------------------------- /bizCore/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | -------------------------------------------------------------------------------- /bizCore/src/main/java/com/lzy/bizcore/AppConfig.java: -------------------------------------------------------------------------------- 1 | package com.lzy.bizcore; 2 | 3 | import android.content.Context; 4 | 5 | import com.lzy.utils.system.DeviceUtil; 6 | import com.lzy.utils.system.ScreenUtil; 7 | 8 | /** 9 | * 全局app信息 10 | * 11 | * @author: cyli8 12 | * @date: 2018/3/8 10:14 13 | */ 14 | 15 | public class AppConfig { 16 | public static String IMEI; 17 | public static String ANDROID_ID; 18 | 19 | public static boolean DEBUG; 20 | public static int VERSION_CODE; 21 | public static String VERSION_NAME; 22 | public static String APP_NAME; 23 | public static String PACKAGE_NAME; 24 | public static String CHANNEL; 25 | 26 | public static int SCREEN_WIDTH; 27 | public static int SCREEN_HEIGHT; 28 | 29 | public static void init(Context context, boolean debug, int versionCode, String versionName, 30 | String appName, String packageName, String channel) { 31 | DEBUG = debug; 32 | VERSION_CODE = versionCode; 33 | VERSION_NAME = versionName; 34 | APP_NAME = appName; 35 | CHANNEL = channel; 36 | PACKAGE_NAME = packageName; 37 | IMEI = DeviceUtil.getIMEI(context); 38 | ANDROID_ID = DeviceUtil.getAndroidID(context); 39 | SCREEN_WIDTH = ScreenUtil.getScreenWidth(context); 40 | SCREEN_HEIGHT = ScreenUtil.getScreenHeight(context); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /bizCore/src/main/java/com/lzy/bizcore/file/FolderManager.java: -------------------------------------------------------------------------------- 1 | package com.lzy.bizcore.file; 2 | 3 | import android.os.Environment; 4 | 5 | import com.lzy.utils.file.FileUtil; 6 | 7 | import java.io.File; 8 | import java.io.IOException; 9 | 10 | import okio.BufferedSink; 11 | import okio.BufferedSource; 12 | import okio.Okio; 13 | import okio.Sink; 14 | import okio.Source; 15 | 16 | /** 17 | * 文件目录管理器,统一管理客户端的文件目录 18 | * 19 | * @author: cyli8 20 | * @date: 2018/2/11 16:07 21 | */ 22 | 23 | public class FolderManager { 24 | private static final String DEFAULT_BASE_DIR = Environment 25 | .getExternalStorageDirectory().getAbsolutePath() 26 | + File.separator 27 | + "fastdevelop" 28 | + File.separator; 29 | 30 | private static FolderManager mInstance; 31 | 32 | public static synchronized FolderManager getInstance() { 33 | if (mInstance == null) { 34 | mInstance = new FolderManager(); 35 | } 36 | return mInstance; 37 | } 38 | 39 | /** 40 | * 获取客户端的目录 41 | * 42 | * @return 客户端目录 43 | */ 44 | public String getClientDir() { 45 | FileUtil.ensureDirExist(DEFAULT_BASE_DIR); 46 | return DEFAULT_BASE_DIR; 47 | } 48 | 49 | 50 | public static boolean copyFile(File origin, File target) { 51 | try { 52 | Source source = Okio.source(origin); 53 | BufferedSource bufferedSource = Okio.buffer(source); 54 | 55 | Sink sink = Okio.sink(target); 56 | BufferedSink bufferedSink = Okio.buffer(sink); 57 | 58 | while (!bufferedSource.exhausted()) { 59 | bufferedSource.read(bufferedSink.buffer(), 8 * 1024); 60 | bufferedSink.emit(); 61 | } 62 | bufferedSource.close(); 63 | bufferedSink.close(); 64 | return true; 65 | } catch (IOException e) { 66 | return false; 67 | } 68 | } 69 | 70 | } 71 | -------------------------------------------------------------------------------- /bizCore/src/main/java/com/lzy/bizcore/helper/NotifiManager.java: -------------------------------------------------------------------------------- 1 | package com.lzy.bizcore.helper; 2 | 3 | import android.app.Notification; 4 | import android.app.NotificationChannel; 5 | import android.app.NotificationManager; 6 | import android.app.PendingIntent; 7 | import android.content.Context; 8 | import android.graphics.BitmapFactory; 9 | import android.os.Build; 10 | import android.view.View; 11 | import android.widget.RemoteViews; 12 | 13 | import com.lzy.bizcore.R; 14 | import com.lzy.utils.StringUtil; 15 | import com.lzy.utils.TimeUtil; 16 | 17 | /** 18 | * 通知管理器 19 | * 20 | * @author: cyli8 21 | * @date: 2018/3/8 09:02 22 | */ 23 | 24 | public class NotifiManager { 25 | 26 | private static final String TAG = "NotificationMgr"; 27 | 28 | private static final int NOTIFICATION_ID_1 = 1;//消息推送-系统通知 29 | private static final int NOTIFICATION_ID_2 = 2;//消息推送-系统消息 30 | public static final int NOTIFICATION_ID_3 = 3;//本地推送 31 | 32 | public static final String PRIMARY_CHANNEL_ID = "default_id"; 33 | 34 | private static Notification getCustomNotification(Context context, String ticker, String title, 35 | String content, PendingIntent pendingIntent, PendingIntent deleteIntent, 36 | NotificationManager mgr) { 37 | Notification notification; 38 | RemoteViews contentView = new RemoteViews(context.getPackageName(), 39 | R.layout.biz_core_custom_notification_item_layout); 40 | contentView.setTextViewText(R.id.custom_notification_time, TimeUtil.getSpecialFormatTime("HH:mm", System.currentTimeMillis())); 41 | contentView.setTextViewText(R.id.custom_notification_title, title); 42 | contentView.setTextViewText(R.id.custom_notification_content, content); 43 | if (StringUtil.isTrimEmpty(title)) { 44 | contentView.setViewVisibility(R.id.custom_notification_title, View.GONE); 45 | } 46 | if (StringUtil.isTrimEmpty(content)) { 47 | contentView.setViewVisibility(R.id.custom_notification_content, View.GONE); 48 | } 49 | int smallIcon = R.mipmap.biz_core_icon_small_alpha; 50 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { 51 | NotificationChannel channel = new NotificationChannel(PRIMARY_CHANNEL_ID, "消息通知", NotificationManager.IMPORTANCE_DEFAULT); 52 | mgr.createNotificationChannel(channel); 53 | notification = new Notification.Builder(context, PRIMARY_CHANNEL_ID) 54 | .setSmallIcon(R.mipmap.biz_core_icon_small_alpha) 55 | .setTicker(ticker) 56 | .setWhen(System.currentTimeMillis()) 57 | .setLargeIcon(BitmapFactory.decodeResource(context.getResources(), R.mipmap.biz_core_icon_large)) 58 | .setContentTitle(title) 59 | .setContentText(content) 60 | .setContentIntent(pendingIntent) 61 | .setDeleteIntent(deleteIntent) 62 | .build(); 63 | } else { 64 | notification = new Notification.Builder(context) 65 | .setSmallIcon(smallIcon) 66 | .setTicker(ticker).setWhen(System.currentTimeMillis()) 67 | .setLargeIcon(BitmapFactory.decodeResource(context.getResources(), R.mipmap.biz_core_icon_large)) 68 | .setContentTitle(title) 69 | .setContentText(content) 70 | .setContentIntent(pendingIntent) 71 | .setDeleteIntent(deleteIntent) 72 | .build(); 73 | } 74 | notification.flags |= Notification.FLAG_AUTO_CANCEL; //自动终止 75 | notification.defaults |= Notification.DEFAULT_SOUND; //默认声音 76 | return notification; 77 | } 78 | 79 | /** 80 | * 本地推送使用 81 | */ 82 | public static void startNotify(Context context, String title, 83 | String content, PendingIntent pendingIntent) { 84 | NotificationManager mgr = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); 85 | if (mgr == null) { 86 | return; 87 | } 88 | Notification notification; 89 | notification = getCustomNotification(context, title, title, 90 | content, pendingIntent, null, mgr); 91 | mgr.notify(NOTIFICATION_ID_3, notification); 92 | } 93 | 94 | public static void cancelNotify(Context context, int id) { 95 | NotificationManager mNotifyManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); 96 | if (mNotifyManager == null) { 97 | return; 98 | } 99 | mNotifyManager.cancel(id); 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /bizCore/src/main/java/com/lzy/bizcore/webview/WebViewFragment.java: -------------------------------------------------------------------------------- 1 | package com.lzy.bizcore.webview; 2 | 3 | import android.annotation.SuppressLint; 4 | import android.app.Activity; 5 | import android.graphics.Bitmap; 6 | import android.os.Bundle; 7 | import android.text.TextUtils; 8 | import android.view.LayoutInflater; 9 | import android.view.View; 10 | import android.view.ViewGroup; 11 | import android.webkit.JsResult; 12 | import android.webkit.WebResourceError; 13 | import android.webkit.WebResourceRequest; 14 | import android.webkit.WebView; 15 | import android.widget.ProgressBar; 16 | import android.widget.RelativeLayout; 17 | 18 | import androidx.annotation.Nullable; 19 | 20 | import com.lzy.bizcore.AppConfig; 21 | import com.lzy.bizcore.R; 22 | import com.lzy.libview.activity.BaseTitleFragmentActivity; 23 | import com.lzy.libview.fragment.BaseFragment; 24 | import com.lzy.utils.StringUtil; 25 | import com.orhanobut.logger.Logger; 26 | 27 | /** 28 | * 内嵌浏览器页面 29 | * 30 | * @author: cyli8 31 | * @date: 2018/3/8 09:55 32 | */ 33 | 34 | public class WebViewFragment extends BaseFragment implements WebViewHelper.OnWebViewListener, WebViewHelper.OnWebChromeListener { 35 | private static final String TAG = "WebViewFragment"; 36 | 37 | public static final String KEY_WEB_VIEW_TITLE = "key_web_view_title"; 38 | public static final String KEY_WEB_VIEW_URL = "key_web_view_url"; 39 | 40 | protected RelativeLayout mWebViewLayout; 41 | protected WebView mWebView; 42 | protected String mUrl; 43 | private String mTitle; 44 | private ProgressBar mProgressBar; 45 | 46 | @Override 47 | protected void initArgument(Bundle bundle) { 48 | if (bundle != null) { 49 | mTitle = bundle.getString(KEY_WEB_VIEW_TITLE); 50 | mUrl = bundle.getString(KEY_WEB_VIEW_URL); 51 | Logger.t(TAG).i("h5地址: " + mUrl); 52 | } 53 | } 54 | 55 | @Nullable 56 | @Override 57 | public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { 58 | View view = inflater.inflate(getLayoutID(), null); 59 | initView(view); 60 | buildWebView(mWebViewLayout); 61 | mWebView.setVisibility(View.VISIBLE); 62 | mWebView.loadUrl(mUrl); 63 | return view; 64 | } 65 | 66 | protected void initView(View view) { 67 | mProgressBar = view.findViewById(R.id.web_view_pb); 68 | mWebViewLayout = view.findViewById(R.id.webview_layout); 69 | } 70 | 71 | protected int getLayoutID() { 72 | return R.layout.biz_core_fragment_webview; 73 | } 74 | 75 | /** 76 | * 创建内嵌的webview,并对相关属性进行设置 77 | * 78 | * @param relativeLayout 页面布局 79 | */ 80 | @SuppressLint({"SetJavaScriptEnabled", "AddJavascriptInterface"}) 81 | private void buildWebView(RelativeLayout relativeLayout) { 82 | WebViewHelper helper = new WebViewHelper(getContext()); 83 | helper.setWebViewListener(this); 84 | helper.setWebChromListener(this); 85 | mWebView = helper.initWebView(true); 86 | RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams( 87 | ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); 88 | relativeLayout.addView(mWebView, layoutParams); 89 | } 90 | 91 | private void pageStart() { 92 | mProgressBar.setVisibility(View.VISIBLE); 93 | } 94 | 95 | private void pageEnd() { 96 | mProgressBar.setVisibility(View.GONE); 97 | } 98 | 99 | private void changeProgress(int progress) { 100 | mProgressBar.setProgress(progress); 101 | } 102 | 103 | @Override 104 | public void onPageStarted(WebView view, String url, Bitmap favicon) { 105 | pageStart(); 106 | } 107 | 108 | @Override 109 | public void onPageFinished(WebView view, String url) { 110 | pageEnd(); 111 | } 112 | 113 | @Override 114 | public void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error) { 115 | pageEnd(); 116 | } 117 | 118 | @Override 119 | public boolean onKeyBack() { 120 | handleGoBack(); 121 | return false; 122 | } 123 | 124 | private void handleGoBack() { 125 | if (mWebView.canGoBack()) { 126 | mWebView.goBack(); 127 | } else { 128 | backToClient(); 129 | } 130 | } 131 | 132 | private void backToClient() { 133 | if (getActivity() != null) { 134 | getActivity().finish(); 135 | } 136 | } 137 | 138 | @Override 139 | public void onProgressChanged(WebView view, int newProgress) { 140 | changeProgress(newProgress); 141 | } 142 | 143 | @Override 144 | public void onReceivedTitle(WebView view, String title) { 145 | if (StringUtil.isTrimEmpty(mTitle)) { 146 | if (!TextUtils.isEmpty(title)) { 147 | mTitle = title; 148 | } else { 149 | mTitle = AppConfig.APP_NAME; 150 | } 151 | Activity a = getActivity(); 152 | if (a instanceof BaseTitleFragmentActivity) { 153 | ((BaseTitleFragmentActivity) getActivity()).setTitle(mTitle); 154 | } 155 | } 156 | } 157 | 158 | @Override 159 | public boolean onJsAlert(WebView view, String url, String message, JsResult result) { 160 | return false; 161 | } 162 | 163 | @Override 164 | public void onDestroy() { 165 | super.onDestroy(); 166 | mWebViewLayout.removeAllViews(); 167 | if (null != mWebView) { 168 | mWebView.setVisibility(View.GONE); 169 | mWebView.removeAllViews(); 170 | mWebView.destroy(); 171 | } 172 | } 173 | } 174 | -------------------------------------------------------------------------------- /bizCore/src/main/java/com/lzy/bizcore/webview/WebViewHelper.java: -------------------------------------------------------------------------------- 1 | package com.lzy.bizcore.webview; 2 | 3 | import android.annotation.SuppressLint; 4 | import android.content.Context; 5 | import android.content.Intent; 6 | import android.graphics.Bitmap; 7 | import android.net.Uri; 8 | import android.net.http.SslError; 9 | import android.os.Build; 10 | import android.view.KeyEvent; 11 | import android.view.View; 12 | import android.webkit.CookieManager; 13 | import android.webkit.JsResult; 14 | import android.webkit.SslErrorHandler; 15 | import android.webkit.WebChromeClient; 16 | import android.webkit.WebResourceError; 17 | import android.webkit.WebResourceRequest; 18 | import android.webkit.WebSettings; 19 | import android.webkit.WebView; 20 | import android.webkit.WebViewClient; 21 | 22 | import com.lzy.bizcore.AppConfig; 23 | import com.lzy.utils.IntentUtil; 24 | import com.lzy.utils.StringUtil; 25 | import com.orhanobut.logger.Logger; 26 | 27 | 28 | /** 29 | * 封装WebView 30 | * 31 | * @author: cyli8 32 | * @date: 2018/3/26 14:39 33 | */ 34 | 35 | public class WebViewHelper { 36 | 37 | private static final String TAG = "WebViewHelper"; 38 | 39 | public interface OnWebViewListener { 40 | void onPageStarted(WebView view, String url, Bitmap favicon); 41 | 42 | void onPageFinished(WebView view, String url); 43 | 44 | void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error); 45 | 46 | boolean onKeyBack(); 47 | } 48 | 49 | private OnWebViewListener mWebViewListener; 50 | 51 | public void setWebViewListener(OnWebViewListener listener) { 52 | mWebViewListener = listener; 53 | } 54 | 55 | public interface OnWebChromeListener { 56 | void onProgressChanged(WebView view, int newProgress); 57 | 58 | void onReceivedTitle(WebView view, String title); 59 | 60 | boolean onJsAlert(WebView view, String url, String message, JsResult result); 61 | } 62 | 63 | private OnWebChromeListener mWebChromeListener; 64 | 65 | public void setWebChromListener(OnWebChromeListener listener) { 66 | mWebChromeListener = listener; 67 | } 68 | 69 | protected Context mContext; 70 | 71 | public WebViewHelper(Context context) { 72 | mContext = context; 73 | } 74 | 75 | private WebViewJsInject mJsInject; 76 | 77 | /** 78 | * 设置注入的对象,在initWebView方法之前调用 79 | * 80 | * @param jsInject 注入的对象 81 | */ 82 | public void setJsInject(WebViewJsInject jsInject) { 83 | mJsInject = jsInject; 84 | } 85 | 86 | @SuppressLint({"SetJavaScriptEnabled", "JavascriptInterface"}) 87 | public WebView initWebView(boolean appContext) { 88 | final WebView webView; 89 | if (appContext) { 90 | webView = new WebView(mContext.getApplicationContext()); 91 | } else { 92 | webView = new WebView(mContext); 93 | } 94 | //setWebViewClient部分 95 | webView.setWebViewClient(new WebViewClient() { 96 | @Override 97 | public boolean shouldOverrideUrlLoading(WebView view, String url) { 98 | Logger.t(TAG).i("shouldOverrideUrlLoading:url:" + url); 99 | if (StringUtil.isEmpty(url) && !url.startsWith("http://") && !url.startsWith("https://")) { 100 | Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); 101 | if (IntentUtil.isActivityCanJump(mContext, intent)) { 102 | try { 103 | mContext.startActivity(intent); 104 | return true; 105 | } catch (Exception e) { 106 | e.printStackTrace(); 107 | } 108 | } 109 | } 110 | return super.shouldOverrideUrlLoading(view, url); 111 | } 112 | 113 | @Override 114 | public void onPageStarted(WebView view, String url, Bitmap favicon) { 115 | super.onPageStarted(view, url, favicon); 116 | Logger.t(TAG).i("onPageStarted"); 117 | if (mWebViewListener != null) { 118 | mWebViewListener.onPageStarted(view, url, favicon); 119 | } 120 | } 121 | 122 | @Override 123 | public void onPageFinished(WebView view, String url) { 124 | super.onPageFinished(view, url); 125 | Logger.t(TAG).i("onPageFinished"); 126 | //防止注入的js对象为空 127 | injectNative(webView); 128 | if (mWebViewListener != null) { 129 | mWebViewListener.onPageFinished(view, url); 130 | } 131 | } 132 | 133 | @Override 134 | public void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error) { 135 | super.onReceivedError(view, request, error); 136 | Logger.t(TAG).i("onReceivedError: 页面加载失败"); 137 | if (null != error) { 138 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { 139 | Logger.t(TAG).i("onReceivedError:" + error.getDescription() + error.getErrorCode()); 140 | } 141 | } 142 | if (mWebViewListener != null) { 143 | mWebViewListener.onReceivedError(view, request, error); 144 | } 145 | } 146 | 147 | @Override 148 | public void onReceivedSslError(WebView view, final SslErrorHandler handler, SslError error) { 149 | Logger.t(TAG).i("onReceivedSslError: 页面加载失败"); 150 | handler.proceed(); 151 | } 152 | }); 153 | //按键监听部分 154 | webView.setOnKeyListener(new View.OnKeyListener() { 155 | @Override 156 | public boolean onKey(View v, int keyCode, KeyEvent event) { 157 | if (event.getAction() == KeyEvent.ACTION_DOWN) { 158 | if (keyCode == KeyEvent.KEYCODE_BACK) { 159 | if (mWebViewListener != null && mWebViewListener.onKeyBack()) { 160 | return true; 161 | } 162 | } 163 | } 164 | return false; 165 | } 166 | }); 167 | //setWebChromeClient部分 168 | webView.setWebChromeClient(new WebChromeClient() { 169 | @Override 170 | public void onProgressChanged(WebView view, int newProgress) { 171 | super.onProgressChanged(view, newProgress); 172 | Logger.t(TAG).i("onProgressChanged=" + newProgress); 173 | if (mWebChromeListener != null) { 174 | mWebChromeListener.onProgressChanged(view, newProgress); 175 | } 176 | } 177 | 178 | @Override 179 | public void onReceivedTitle(WebView view, String title) { 180 | super.onReceivedTitle(view, title); 181 | Logger.t(TAG).i("onReceivedTitle=" + title); 182 | if (mWebChromeListener != null) { 183 | mWebChromeListener.onReceivedTitle(view, title); 184 | } 185 | } 186 | 187 | @Override 188 | public boolean onJsAlert(WebView view, String url, String message, JsResult result) { 189 | Logger.t(TAG).i("onJsAlert : " + message); 190 | if (mWebViewListener != null && mWebChromeListener.onJsAlert(view, url, message, result)) { 191 | result.confirm(); 192 | return true; 193 | } 194 | return super.onJsAlert(view, url, message, result); 195 | } 196 | }); 197 | //WebSettings部分 198 | webView.requestFocus(View.FOCUS_DOWN); 199 | WebSettings settings = webView.getSettings(); 200 | settings.setDatabaseEnabled(true); 201 | //不缓存 202 | settings.setCacheMode(WebSettings.LOAD_NO_CACHE); 203 | settings.setGeolocationEnabled(true); 204 | settings.setAllowContentAccess(true); 205 | settings.setBlockNetworkLoads(false); 206 | settings.setBlockNetworkImage(false); 207 | settings.setDomStorageEnabled(true); 208 | settings.setAllowFileAccess(true); 209 | settings.setJavaScriptCanOpenWindowsAutomatically(true); 210 | settings.setMediaPlaybackRequiresUserGesture(false); 211 | //这里需要设置为true,才能让Webivew支持标签的viewport属性 212 | settings.setUseWideViewPort(true); 213 | settings.setAppCacheEnabled(true); 214 | String dir = mContext.getApplicationContext() 215 | .getDir("appcache", Context.MODE_PRIVATE).getPath(); 216 | settings.setAppCachePath(dir); 217 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { 218 | settings.setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW); 219 | } 220 | settings.setUserAgentString(settings.getUserAgentString()); 221 | settings.setJavaScriptEnabled(true); 222 | injectNative(webView); 223 | WebView.setWebContentsDebuggingEnabled(AppConfig.DEBUG); 224 | //开启硬件加速,支持播放视频 225 | webView.setLayerType(View.LAYER_TYPE_HARDWARE, null); 226 | CookieManager cookieManager = CookieManager.getInstance(); 227 | cookieManager.setAcceptCookie(true); 228 | cookieManager.setAcceptThirdPartyCookies(webView, true); 229 | return webView; 230 | } 231 | 232 | @SuppressLint("JavascriptInterface") 233 | private void injectNative(WebView webView) { 234 | if (mJsInject != null) { 235 | webView.addJavascriptInterface(mJsInject, WebViewJsInject.INJECT_OBJECT_ALIAS); 236 | } 237 | } 238 | 239 | } 240 | -------------------------------------------------------------------------------- /bizCore/src/main/java/com/lzy/bizcore/webview/WebViewJsInject.java: -------------------------------------------------------------------------------- 1 | package com.lzy.bizcore.webview; 2 | 3 | /** 4 | * @author: cyli8 5 | * @date: 2019-12-12 15:15 6 | */ 7 | public class WebViewJsInject { 8 | public static final String INJECT_OBJECT_ALIAS = "fasedevelop"; 9 | } 10 | -------------------------------------------------------------------------------- /bizCore/src/main/res/layout/biz_core_custom_notification_item_layout.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 16 | 17 | 24 | 25 | 32 | 33 | 41 | 42 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /bizCore/src/main/res/layout/biz_core_fragment_webview.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 16 | 17 | 23 | 24 | -------------------------------------------------------------------------------- /bizCore/src/main/res/mipmap-xxhdpi/biz_core_icon_large.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lzyang187/FastDevelop/86dc57026a8b4e9b193891edbecb6ee594de157a/bizCore/src/main/res/mipmap-xxhdpi/biz_core_icon_large.png -------------------------------------------------------------------------------- /bizCore/src/main/res/mipmap-xxhdpi/biz_core_icon_small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lzyang187/FastDevelop/86dc57026a8b4e9b193891edbecb6ee594de157a/bizCore/src/main/res/mipmap-xxhdpi/biz_core_icon_small.png -------------------------------------------------------------------------------- /bizCore/src/main/res/mipmap-xxhdpi/biz_core_icon_small_alpha.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lzyang187/FastDevelop/86dc57026a8b4e9b193891edbecb6ee594de157a/bizCore/src/main/res/mipmap-xxhdpi/biz_core_icon_small_alpha.png -------------------------------------------------------------------------------- /bizCore/src/main/res/values/ids.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /bizCore/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | bizCore 3 | 4 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | 3 | buildscript { 4 | 5 | repositories { 6 | google() 7 | mavenCentral() 8 | jcenter() 9 | } 10 | dependencies { 11 | classpath 'com.android.tools.build:gradle:4.2.0' 12 | classpath 'com.mcxiaoke.packer-ng:plugin:2.0.1' 13 | 14 | // NOTE: Do not place your application dependencies here; they belong 15 | // in the individual module build.gradle files 16 | } 17 | } 18 | 19 | allprojects { 20 | repositories { 21 | google() 22 | mavenCentral() 23 | jcenter() 24 | } 25 | } 26 | 27 | task clean(type: Delete) { 28 | delete rootProject.buildDir 29 | } 30 | 31 | ext { 32 | //android配置的一些常量 33 | minSdkVersion = 21 34 | compileSdkVersion = 28 35 | targetSdkVersion = 27 36 | androidXVersion = '1.1.0' 37 | versionCode = 1 38 | versionName = "1" 39 | } 40 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | 3 | # IDE (e.g. Android Studio) users: 4 | # Gradle settings configured through the IDE *will override* 5 | # any settings specified in this file. 6 | 7 | # For more details on how to configure your build environment visit 8 | # http://www.gradle.org/docs/current/userguide/build_environment.html 9 | 10 | # Specifies the JVM arguments used for the daemon process. 11 | # The setting is particularly useful for tweaking memory settings. 12 | org.gradle.jvmargs=-Xmx1536m 13 | 14 | # When configured, Gradle will run in incubating parallel mode. 15 | # This option should only be used with decoupled projects. More details, visit 16 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 17 | # org.gradle.parallel=true 18 | 19 | #AndroidX 20 | android.useAndroidX=true 21 | android.enableJetifier=true -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lzyang187/FastDevelop/86dc57026a8b4e9b193891edbecb6ee594de157a/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Sun Feb 11 11:05:11 CST 2018 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-6.7.1-all.zip 7 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 10 | DEFAULT_JVM_OPTS="" 11 | 12 | APP_NAME="Gradle" 13 | APP_BASE_NAME=`basename "$0"` 14 | 15 | # Use the maximum available, or set MAX_FD != -1 to use that value. 16 | MAX_FD="maximum" 17 | 18 | warn ( ) { 19 | echo "$*" 20 | } 21 | 22 | die ( ) { 23 | echo 24 | echo "$*" 25 | echo 26 | exit 1 27 | } 28 | 29 | # OS specific support (must be 'true' or 'false'). 30 | cygwin=false 31 | msys=false 32 | darwin=false 33 | case "`uname`" in 34 | CYGWIN* ) 35 | cygwin=true 36 | ;; 37 | Darwin* ) 38 | darwin=true 39 | ;; 40 | MINGW* ) 41 | msys=true 42 | ;; 43 | esac 44 | 45 | # Attempt to set APP_HOME 46 | # Resolve links: $0 may be a link 47 | PRG="$0" 48 | # Need this for relative symlinks. 49 | while [ -h "$PRG" ] ; do 50 | ls=`ls -ld "$PRG"` 51 | link=`expr "$ls" : '.*-> \(.*\)$'` 52 | if expr "$link" : '/.*' > /dev/null; then 53 | PRG="$link" 54 | else 55 | PRG=`dirname "$PRG"`"/$link" 56 | fi 57 | done 58 | SAVED="`pwd`" 59 | cd "`dirname \"$PRG\"`/" >/dev/null 60 | APP_HOME="`pwd -P`" 61 | cd "$SAVED" >/dev/null 62 | 63 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 64 | 65 | # Determine the Java command to use to start the JVM. 66 | if [ -n "$JAVA_HOME" ] ; then 67 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 68 | # IBM's JDK on AIX uses strange locations for the executables 69 | JAVACMD="$JAVA_HOME/jre/sh/java" 70 | else 71 | JAVACMD="$JAVA_HOME/bin/java" 72 | fi 73 | if [ ! -x "$JAVACMD" ] ; then 74 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 75 | 76 | Please set the JAVA_HOME variable in your environment to match the 77 | location of your Java installation." 78 | fi 79 | else 80 | JAVACMD="java" 81 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 82 | 83 | Please set the JAVA_HOME variable in your environment to match the 84 | location of your Java installation." 85 | fi 86 | 87 | # Increase the maximum file descriptors if we can. 88 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then 89 | MAX_FD_LIMIT=`ulimit -H -n` 90 | if [ $? -eq 0 ] ; then 91 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 92 | MAX_FD="$MAX_FD_LIMIT" 93 | fi 94 | ulimit -n $MAX_FD 95 | if [ $? -ne 0 ] ; then 96 | warn "Could not set maximum file descriptor limit: $MAX_FD" 97 | fi 98 | else 99 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 100 | fi 101 | fi 102 | 103 | # For Darwin, add options to specify how the application appears in the dock 104 | if $darwin; then 105 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 106 | fi 107 | 108 | # For Cygwin, switch paths to Windows format before running java 109 | if $cygwin ; then 110 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 111 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 112 | JAVACMD=`cygpath --unix "$JAVACMD"` 113 | 114 | # We build the pattern for arguments to be converted via cygpath 115 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 116 | SEP="" 117 | for dir in $ROOTDIRSRAW ; do 118 | ROOTDIRS="$ROOTDIRS$SEP$dir" 119 | SEP="|" 120 | done 121 | OURCYGPATTERN="(^($ROOTDIRS))" 122 | # Add a user-defined pattern to the cygpath arguments 123 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 124 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 125 | fi 126 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 127 | i=0 128 | for arg in "$@" ; do 129 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 130 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 131 | 132 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 133 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 134 | else 135 | eval `echo args$i`="\"$arg\"" 136 | fi 137 | i=$((i+1)) 138 | done 139 | case $i in 140 | (0) set -- ;; 141 | (1) set -- "$args0" ;; 142 | (2) set -- "$args0" "$args1" ;; 143 | (3) set -- "$args0" "$args1" "$args2" ;; 144 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 145 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 146 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 147 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 148 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 149 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 150 | esac 151 | fi 152 | 153 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules 154 | function splitJvmOpts() { 155 | JVM_OPTS=("$@") 156 | } 157 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS 158 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" 159 | 160 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" 161 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 12 | set DEFAULT_JVM_OPTS= 13 | 14 | set DIRNAME=%~dp0 15 | if "%DIRNAME%" == "" set DIRNAME=. 16 | set APP_BASE_NAME=%~n0 17 | set APP_HOME=%DIRNAME% 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windowz variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /libBaseFun/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /libBaseFun/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | 3 | android { 4 | compileSdkVersion rootProject.ext.compileSdkVersion 5 | 6 | defaultConfig { 7 | minSdkVersion rootProject.ext.minSdkVersion 8 | targetSdkVersion rootProject.ext.targetSdkVersion 9 | versionCode 1 10 | versionName "1.0" 11 | 12 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 13 | consumerProguardFiles 'consumer-rules.pro' 14 | } 15 | 16 | buildTypes { 17 | release { 18 | minifyEnabled true 19 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' 20 | } 21 | } 22 | 23 | resourcePrefix "lib_basefun_" 24 | 25 | } 26 | 27 | dependencies { 28 | implementation fileTree(dir: 'libs', include: ['*.jar']) 29 | implementation project(':libHttp') 30 | //rxJava 31 | api "io.reactivex.rxjava2:rxjava:2.2.6" 32 | api 'io.reactivex.rxjava2:rxandroid:2.1.1' 33 | //glide 34 | api 'com.github.bumptech.glide:glide:4.9.0' 35 | annotationProcessor 'com.github.bumptech.glide:compiler:4.9.0' 36 | //解决Glide找不到Android声明库问题 37 | annotationProcessor 'androidx.annotation:annotation:1.1.0' 38 | implementation 'com.github.bumptech.glide:okhttp3-integration:4.9.0' 39 | //变换库 40 | api 'jp.wasabeef:glide-transformations:4.0.0' 41 | //RecyclerView集成库 42 | api("com.github.bumptech.glide:recyclerview-integration:4.9.0") { 43 | // Excludes the support library because it's already included by Glide. 44 | transitive = false 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /libBaseFun/consumer-rules.pro: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lzyang187/FastDevelop/86dc57026a8b4e9b193891edbecb6ee594de157a/libBaseFun/consumer-rules.pro -------------------------------------------------------------------------------- /libBaseFun/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | -------------------------------------------------------------------------------- /libBaseFun/src/androidTest/java/com/lzy/libbasefun/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package com.lzy.libbasefun; 2 | 3 | import android.content.Context; 4 | 5 | import androidx.test.platform.app.InstrumentationRegistry; 6 | import androidx.test.ext.junit.runners.AndroidJUnit4; 7 | 8 | import org.junit.Test; 9 | import org.junit.runner.RunWith; 10 | 11 | import static org.junit.Assert.*; 12 | 13 | /** 14 | * Instrumented test, which will execute on an Android device. 15 | * 16 | * @see Testing documentation 17 | */ 18 | @RunWith(AndroidJUnit4.class) 19 | public class ExampleInstrumentedTest { 20 | @Test 21 | public void useAppContext() { 22 | // Context of the app under test. 23 | Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext(); 24 | 25 | assertEquals("com.lzy.libbasefun.test", appContext.getPackageName()); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /libBaseFun/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | -------------------------------------------------------------------------------- /libBaseFun/src/main/java/com/lzy/libbasefun/glide/module/MyAppGlideModule.java: -------------------------------------------------------------------------------- 1 | package com.lzy.libbasefun.glide.module; 2 | 3 | import android.content.Context; 4 | 5 | import com.bumptech.glide.GlideBuilder; 6 | import com.bumptech.glide.annotation.GlideModule; 7 | import com.bumptech.glide.load.engine.cache.ExternalPreferredCacheDiskCacheFactory; 8 | import com.bumptech.glide.module.AppGlideModule; 9 | 10 | /** 11 | * @author: cyli8 12 | * @date: 2019-11-27 11:53 13 | */ 14 | @GlideModule 15 | public class MyAppGlideModule extends AppGlideModule { 16 | 17 | //更改Glide配置 18 | @Override 19 | public void applyOptions(Context context, GlideBuilder builder) { 20 | //设置Glide图片缓存位置是SD卡 21 | long cacheSize = 500 * 1025 * 1024;//500MB 22 | builder.setDiskCache(new ExternalPreferredCacheDiskCacheFactory(context, cacheSize)); 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /libBaseFun/src/main/java/com/lzy/libbasefun/glide/module/OkHttpLibraryGlideModule.java: -------------------------------------------------------------------------------- 1 | package com.lzy.libbasefun.glide.module; 2 | 3 | import android.content.Context; 4 | 5 | import androidx.annotation.NonNull; 6 | 7 | import com.bumptech.glide.Glide; 8 | import com.bumptech.glide.Registry; 9 | import com.bumptech.glide.annotation.GlideModule; 10 | import com.bumptech.glide.integration.okhttp3.OkHttpUrlLoader; 11 | import com.bumptech.glide.load.model.GlideUrl; 12 | import com.bumptech.glide.module.LibraryGlideModule; 13 | import com.lzy.libhttp.MyOkHttpClient; 14 | 15 | import java.io.InputStream; 16 | 17 | /** 18 | * @author: cyli8 19 | * @date: 2019-11-26 17:28 20 | */ 21 | @GlideModule 22 | public class OkHttpLibraryGlideModule extends LibraryGlideModule { 23 | @Override 24 | public void registerComponents(@NonNull Context context, @NonNull Glide glide, @NonNull Registry registry) { 25 | registry.replace(GlideUrl.class, InputStream.class, new OkHttpUrlLoader.Factory(MyOkHttpClient.getInstance().getOkHttpClient())); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /libBaseFun/src/main/java/com/lzy/libbasefun/glide/recyclerview/MyPreloadModelProvider.java: -------------------------------------------------------------------------------- 1 | package com.lzy.libbasefun.glide.recyclerview; 2 | 3 | import android.content.Context; 4 | import android.text.TextUtils; 5 | 6 | import androidx.annotation.NonNull; 7 | import androidx.annotation.Nullable; 8 | 9 | import com.bumptech.glide.Glide; 10 | import com.bumptech.glide.ListPreloader; 11 | import com.bumptech.glide.RequestBuilder; 12 | 13 | import java.util.Collections; 14 | import java.util.List; 15 | 16 | /** 17 | * @author: cyli8 18 | * @date: 2019-12-03 15:18 19 | */ 20 | public class MyPreloadModelProvider implements ListPreloader.PreloadModelProvider { 21 | 22 | private Context context; 23 | private List urls; 24 | 25 | public MyPreloadModelProvider(Context context, List urls) { 26 | this.context = context; 27 | this.urls = urls; 28 | } 29 | 30 | @NonNull 31 | @Override 32 | public List getPreloadItems(int position) { 33 | String url = urls.get(position); 34 | if (TextUtils.isEmpty(url)) { 35 | return Collections.emptyList(); 36 | } 37 | return Collections.singletonList(url); 38 | } 39 | 40 | @Nullable 41 | @Override 42 | public RequestBuilder getPreloadRequestBuilder(@NonNull String item) { 43 | //返回的 RequestBuilder ,必须与你从 onBindViewHolder 里启动的请求使用完全相同的一组选项 (占位符, 变换等) 和完全相同的尺寸 44 | return Glide.with(context) 45 | .load(item) 46 | .centerCrop(); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /libBaseFun/src/main/java/com/lzy/libbasefun/lru/DiskLruCacheMgr.java: -------------------------------------------------------------------------------- 1 | package com.lzy.libbasefun.lru; 2 | 3 | import android.content.Context; 4 | import android.text.TextUtils; 5 | 6 | import java.io.ByteArrayOutputStream; 7 | import java.io.File; 8 | import java.io.IOException; 9 | import java.io.InputStream; 10 | import java.io.ObjectInputStream; 11 | import java.io.ObjectOutputStream; 12 | 13 | import okhttp3.internal.cache.DiskLruCache; 14 | import okhttp3.internal.io.FileSystem; 15 | import okio.BufferedSink; 16 | import okio.BufferedSource; 17 | import okio.Okio; 18 | import okio.Source; 19 | 20 | /** 21 | * @author: cyli8 22 | * @date: 2019-09-29 09:27 23 | */ 24 | public class DiskLruCacheMgr { 25 | private static final String CACHE_FILE_NAME = "lruCache"; 26 | private static final int APP_VERSION = 1; 27 | private static final int EACH_ENTRY_VALUE_COUNT = 1; 28 | private static final int MAX_SIZE = 100 * 1024 * 1024;//100M 29 | private static final int ENTRY_INDEX = 0; 30 | 31 | private static DiskLruCacheMgr mInstance; 32 | private DiskLruCache mDiskLruCache; 33 | 34 | public void init(Context context) { 35 | File cacheFile = new File(context.getExternalCacheDir(), CACHE_FILE_NAME); 36 | if (!cacheFile.exists()) { 37 | cacheFile.mkdirs(); 38 | } 39 | mDiskLruCache = DiskLruCache.create(FileSystem.SYSTEM, cacheFile, APP_VERSION, EACH_ENTRY_VALUE_COUNT, MAX_SIZE); 40 | } 41 | 42 | private DiskLruCacheMgr() { 43 | 44 | } 45 | 46 | public static DiskLruCacheMgr getInstance() { 47 | if (mInstance == null) { 48 | synchronized (DiskLruCacheMgr.class) { 49 | if (mInstance == null) { 50 | mInstance = new DiskLruCacheMgr(); 51 | } 52 | } 53 | } 54 | return mInstance; 55 | } 56 | 57 | public boolean put(String key, Object obj) { 58 | if (TextUtils.isEmpty(key) || obj == null) { 59 | throw new NullPointerException("key or obj 为空"); 60 | } 61 | try { 62 | DiskLruCache.Editor editor = mDiskLruCache.edit(key); 63 | BufferedSink bufferedSink = Okio.buffer(editor.newSink(ENTRY_INDEX)); 64 | ByteArrayOutputStream baos = new ByteArrayOutputStream(); 65 | ObjectOutputStream oos = new ObjectOutputStream(baos); 66 | oos.writeObject(obj); 67 | bufferedSink.write(baos.toByteArray()); 68 | bufferedSink.flush(); 69 | editor.commit(); 70 | return true; 71 | } catch (IOException e) { 72 | e.printStackTrace(); 73 | } 74 | return false; 75 | } 76 | 77 | public Object get(String key) { 78 | try { 79 | DiskLruCache.Snapshot snapshot = mDiskLruCache.get(key); 80 | if (snapshot == null) { 81 | return null; 82 | } 83 | Source source = snapshot.getSource(ENTRY_INDEX); 84 | BufferedSource bufferedSource = Okio.buffer(source); 85 | InputStream inputStream = bufferedSource.inputStream(); 86 | ObjectInputStream ois = new ObjectInputStream(inputStream); 87 | Object object = ois.readObject(); 88 | bufferedSource.close(); 89 | return object; 90 | } catch (IOException | ClassNotFoundException e) { 91 | e.printStackTrace(); 92 | } 93 | return null; 94 | } 95 | 96 | public boolean remove(String key) { 97 | try { 98 | return mDiskLruCache.remove(key); 99 | } catch (IOException e) { 100 | e.printStackTrace(); 101 | } 102 | return false; 103 | } 104 | 105 | } 106 | -------------------------------------------------------------------------------- /libBaseFun/src/main/java/com/lzy/libbasefun/rxjava/RxUtils.java: -------------------------------------------------------------------------------- 1 | package com.lzy.libbasefun.rxjava; 2 | 3 | import io.reactivex.Observable; 4 | import io.reactivex.ObservableSource; 5 | import io.reactivex.ObservableTransformer; 6 | import io.reactivex.Scheduler; 7 | import io.reactivex.android.schedulers.AndroidSchedulers; 8 | import io.reactivex.schedulers.Schedulers; 9 | 10 | /** 11 | * @author: cyli8 12 | * @date: 2019-12-10 20:10 13 | */ 14 | public class RxUtils { 15 | 16 | /** 17 | * io和主线程切换 18 | */ 19 | public static ObservableTransformer rxScheduler() { 20 | return rxScheduler(Schedulers.io()); 21 | } 22 | 23 | public static ObservableTransformer rxScheduler(final Scheduler scheduler) { 24 | return new ObservableTransformer() { 25 | @Override 26 | public ObservableSource apply(Observable upstream) { 27 | return upstream.subscribeOn(scheduler) 28 | .observeOn(AndroidSchedulers.mainThread()); 29 | } 30 | }; 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /libBaseFun/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | libBaseFun 3 | 4 | -------------------------------------------------------------------------------- /libBaseFun/src/test/java/com/lzy/libbasefun/ExampleUnitTest.java: -------------------------------------------------------------------------------- 1 | package com.lzy.libbasefun; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.*; 6 | 7 | /** 8 | * Example local unit test, which will execute on the development machine (host). 9 | * 10 | * @see Testing documentation 11 | */ 12 | public class ExampleUnitTest { 13 | @Test 14 | public void addition_isCorrect() { 15 | assertEquals(4, 2 + 2); 16 | } 17 | } -------------------------------------------------------------------------------- /libFileProvider/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /libFileProvider/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | 3 | android { 4 | compileSdkVersion rootProject.ext.compileSdkVersion 5 | 6 | defaultConfig { 7 | minSdkVersion rootProject.ext.minSdkVersion 8 | targetSdkVersion rootProject.ext.targetSdkVersion 9 | versionCode 1 10 | versionName "1.0" 11 | 12 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 13 | 14 | } 15 | 16 | buildTypes { 17 | release { 18 | minifyEnabled false 19 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 20 | } 21 | 22 | resourcePrefix "lib_fileprovider_" 23 | } 24 | 25 | } 26 | 27 | dependencies { 28 | implementation fileTree(dir: 'libs', include: ['*.jar']) 29 | implementation 'androidx.appcompat:appcompat:' + rootProject.ext.androidXVersion 30 | } 31 | -------------------------------------------------------------------------------- /libFileProvider/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | -------------------------------------------------------------------------------- /libFileProvider/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 10 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /libFileProvider/src/main/java/com/lzy/libfileprovider/FileProviderUtil.java: -------------------------------------------------------------------------------- 1 | package com.lzy.libfileprovider; 2 | 3 | import android.content.Context; 4 | import android.content.Intent; 5 | import android.net.Uri; 6 | import android.os.Build; 7 | 8 | import androidx.core.content.FileProvider; 9 | 10 | import java.io.File; 11 | 12 | /** 13 | * 适配7.0文件uri获取工具类 14 | * 15 | * @author: cyli8 16 | * @date: 2018/7/23 10:09 17 | */ 18 | public class FileProviderUtil { 19 | private static final String AUTHORITY_FILE_PROVIDER_SUFFIX = ".fastdevelop.fileProvider"; 20 | 21 | public static Uri getUriForFile(Context context, File file) { 22 | Uri fileUri; 23 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { 24 | fileUri = getUriByNougat(context, file); 25 | } else { 26 | fileUri = Uri.fromFile(file); 27 | } 28 | return fileUri; 29 | } 30 | 31 | private static Uri getUriByNougat(Context context, File file) { 32 | return FileProvider.getUriForFile(context, context.getPackageName() + AUTHORITY_FILE_PROVIDER_SUFFIX, file); 33 | } 34 | 35 | public static void setIntentDataAndType(Context context, Intent intent, String type, 36 | File file, boolean writeAble) { 37 | intent.setDataAndType(getUriForFile(context, file), type); 38 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { 39 | intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); 40 | if (writeAble) { 41 | intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION); 42 | } 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /libFileProvider/src/main/java/com/lzy/libfileprovider/LibFileProvider.java: -------------------------------------------------------------------------------- 1 | package com.lzy.libfileprovider; 2 | 3 | 4 | import androidx.core.content.FileProvider; 5 | 6 | /** 7 | * @author: cyli8 8 | * @date: 2018/8/23 08:53 9 | */ 10 | public class LibFileProvider extends FileProvider { 11 | 12 | } 13 | -------------------------------------------------------------------------------- /libFileProvider/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | libFileProvider 3 | 4 | -------------------------------------------------------------------------------- /libFileProvider/src/main/res/xml/lib_fileprovider_file_paths.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 10 | 11 | 14 | 15 | 18 | 19 | 22 | 23 | 26 | 27 | -------------------------------------------------------------------------------- /libHttp/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /libHttp/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | 3 | android { 4 | compileSdkVersion rootProject.ext.compileSdkVersion 5 | 6 | defaultConfig { 7 | minSdkVersion rootProject.ext.minSdkVersion 8 | targetSdkVersion rootProject.ext.targetSdkVersion 9 | versionCode 1 10 | versionName "1.0" 11 | 12 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 13 | 14 | } 15 | 16 | buildTypes { 17 | release { 18 | minifyEnabled false 19 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 20 | } 21 | } 22 | 23 | resourcePrefix "lib_http_" 24 | 25 | } 26 | 27 | dependencies { 28 | implementation fileTree(dir: 'libs', include: ['*.jar']) 29 | implementation project(':libUtils') 30 | api 'com.squareup.retrofit2:retrofit:2.5.0' 31 | implementation 'com.squareup.retrofit2:converter-gson:2.5.0' 32 | implementation 'com.jakewharton.retrofit:retrofit2-rxjava2-adapter:1.0.0' 33 | } 34 | -------------------------------------------------------------------------------- /libHttp/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | 23 | #okhttp 24 | -dontwarn okhttp3.** 25 | -keep class okhttp3.**{*;} 26 | 27 | 28 | #okio 29 | -dontwarn okio.** 30 | -keep class okio.**{*;} 31 | -------------------------------------------------------------------------------- /libHttp/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | -------------------------------------------------------------------------------- /libHttp/src/main/java/com/lzy/libhttp/HttpConstants.java: -------------------------------------------------------------------------------- 1 | package com.lzy.libhttp; 2 | 3 | /** 4 | * @author: cyli8 5 | * @date: 2018/7/16 10:15 6 | */ 7 | public class HttpConstants { 8 | public static final int CONNECT_TIMEOUT = 10; 9 | public static final int READ_TIMEOUT = 10; 10 | public static final int WRITE_TIMEOUT = 10; 11 | 12 | /*请求返回码正常*/ 13 | public static final int HTTP_TYPE_OK = 1; 14 | /*请求超时*/ 15 | public static final int HTTP_TYPE_TIMEOUT = -1; 16 | /*网络连接异常*/ 17 | public static final int HTTP_TYPE_NETWORK_ERROR = -2; 18 | /*网络请求服务器错误*/ 19 | public static final int HTTP_TYPE_SERVER_REFUSE = -4; 20 | /*网络请求其他异常*/ 21 | public static final int HTTP_TYPE_OTHER_EXCEPTION = -8; 22 | 23 | } 24 | -------------------------------------------------------------------------------- /libHttp/src/main/java/com/lzy/libhttp/MyOkHttpClient.java: -------------------------------------------------------------------------------- 1 | package com.lzy.libhttp; 2 | 3 | import com.lzy.libhttp.interceptor.LogInterceptor; 4 | 5 | import java.io.File; 6 | import java.util.concurrent.TimeUnit; 7 | 8 | import okhttp3.Cache; 9 | import okhttp3.OkHttpClient; 10 | 11 | /** 12 | * @author: cyli8 13 | * @date: 2019-11-06 15:33 14 | */ 15 | public class MyOkHttpClient { 16 | 17 | private static File mCacheFile; 18 | 19 | public static void setCacheFile(File file) { 20 | mCacheFile = file; 21 | } 22 | 23 | private MyOkHttpClient() { 24 | Cache cache = new Cache(mCacheFile, 10 * 1024 * 1024); 25 | mOkHttpClient = new OkHttpClient().newBuilder() 26 | .connectTimeout(30, TimeUnit.SECONDS) 27 | .readTimeout(30, TimeUnit.SECONDS) 28 | .writeTimeout(30, TimeUnit.SECONDS) 29 | .retryOnConnectionFailure(true) 30 | .cache(cache) 31 | .addInterceptor(new LogInterceptor(true)) 32 | .build(); 33 | } 34 | 35 | private static MyOkHttpClient mInstance; 36 | 37 | public static synchronized MyOkHttpClient getInstance() { 38 | if (mInstance == null) { 39 | mInstance = new MyOkHttpClient(); 40 | } 41 | return mInstance; 42 | } 43 | 44 | private OkHttpClient mOkHttpClient; 45 | 46 | public OkHttpClient getOkHttpClient() { 47 | return mOkHttpClient; 48 | } 49 | 50 | } 51 | -------------------------------------------------------------------------------- /libHttp/src/main/java/com/lzy/libhttp/RetrofitBuildHelper.java: -------------------------------------------------------------------------------- 1 | package com.lzy.libhttp; 2 | 3 | import com.jakewharton.retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory; 4 | 5 | import retrofit2.Retrofit; 6 | import retrofit2.converter.gson.GsonConverterFactory; 7 | 8 | /** 9 | * @author: cyli8 10 | * @date: 2019-11-07 08:55 11 | */ 12 | public class RetrofitBuildHelper { 13 | 14 | public static Retrofit build(String baseUrl) { 15 | return new Retrofit.Builder().baseUrl(baseUrl) 16 | .client(MyOkHttpClient.getInstance().getOkHttpClient()) 17 | .addConverterFactory(GsonConverterFactory.create()) 18 | .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) 19 | .build(); 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /libHttp/src/main/java/com/lzy/libhttp/interceptor/LogInterceptor.java: -------------------------------------------------------------------------------- 1 | package com.lzy.libhttp.interceptor; 2 | 3 | import android.text.TextUtils; 4 | 5 | import com.orhanobut.logger.Logger; 6 | 7 | import java.io.IOException; 8 | 9 | import okhttp3.Headers; 10 | import okhttp3.Interceptor; 11 | import okhttp3.MediaType; 12 | import okhttp3.Request; 13 | import okhttp3.RequestBody; 14 | import okhttp3.Response; 15 | import okhttp3.ResponseBody; 16 | import okio.Buffer; 17 | 18 | /** 19 | * 网络请求日志打印拦截器 20 | * 21 | * @author: cyli8 22 | * @date: 2018/7/16 10:21 23 | */ 24 | public class LogInterceptor implements Interceptor { 25 | private static final String TAG = "LogInterceptor"; 26 | private boolean mShowResponse; 27 | 28 | public LogInterceptor(boolean showResponse) { 29 | this.mShowResponse = showResponse; 30 | } 31 | 32 | @Override 33 | public Response intercept(Chain chain) throws IOException { 34 | Request request = chain.request(); 35 | logForRequest(request); 36 | Response response = chain.proceed(request); 37 | logForResponse(response); 38 | return response; 39 | } 40 | 41 | private void logForRequest(Request request) { 42 | try { 43 | String url = request.url().toString(); 44 | Headers headers = request.headers(); 45 | 46 | Logger.t(TAG).e("========== request'log start =========="); 47 | Logger.t(TAG).e("method : " + request.method()); 48 | Logger.t(TAG).e("url : " + url); 49 | if (headers != null && headers.size() > 0) { 50 | Logger.t(TAG).e("headers : " + headers.toString()); 51 | } 52 | RequestBody requestBody = request.body(); 53 | if (requestBody != null) { 54 | MediaType mediaType = requestBody.contentType(); 55 | if (mediaType != null) { 56 | Logger.t(TAG).e("requestBody's contentType : " + mediaType.toString()); 57 | if (isText(mediaType)) { 58 | Logger.t(TAG).e("requestBody's content : " + bodyToString(request)); 59 | } else { 60 | Logger.t(TAG).e("requestBody's content : " + " maybe [file part] , too large to print , ignored!"); 61 | } 62 | } 63 | } 64 | Logger.t(TAG).e("========== request'log end =========="); 65 | } catch (Exception e) { 66 | } 67 | } 68 | 69 | private boolean isText(MediaType mediaType) { 70 | return mediaType.type() != null && mediaType.type().equals("text") || 71 | mediaType.subtype() != null && (mediaType.subtype().equals("json") || mediaType.subtype().equals("xml") || mediaType.subtype().equals("html") || mediaType.subtype().equals("webviewhtml")); 72 | } 73 | 74 | private String bodyToString(final Request request) { 75 | try { 76 | final Request copy = request.newBuilder().build(); 77 | final Buffer buffer = new Buffer(); 78 | RequestBody body = copy.body(); 79 | if (body != null) { 80 | body.writeTo(buffer); 81 | } 82 | return buffer.readUtf8(); 83 | } catch (final IOException e) { 84 | return "show requestBody error :" + e.getMessage(); 85 | } 86 | } 87 | 88 | private void logForResponse(Response response) { 89 | try { 90 | Logger.t(TAG).e("========== response'log start ========="); 91 | Response.Builder builder = response.newBuilder(); 92 | Response clone = builder.build(); 93 | Logger.t(TAG).e("url : " + clone.request().url()); 94 | Logger.t(TAG).e("code : " + clone.code()); 95 | Logger.t(TAG).e("protocol : " + clone.protocol()); 96 | if (!TextUtils.isEmpty(clone.message())) 97 | Logger.t(TAG).e("message : " + clone.message()); 98 | if (mShowResponse) { 99 | ResponseBody body = clone.body(); 100 | if (body != null) { 101 | MediaType mediaType = body.contentType(); 102 | if (mediaType != null) { 103 | Logger.t(TAG).e("responseBody's contentType : " + mediaType.toString()); 104 | if (isText(mediaType)) { 105 | String resp = body.string(); 106 | Logger.t(TAG).e("responseBody's content : " + resp); 107 | body = ResponseBody.create(mediaType, resp); 108 | response.newBuilder().body(body).build(); 109 | } else { 110 | Logger.t(TAG).e("responseBody's content : " + " maybe [file part] , too large to print , ignored!"); 111 | } 112 | } 113 | } 114 | } 115 | Logger.t(TAG).e("========== response'log end =========="); 116 | } catch (Exception e) { 117 | } 118 | } 119 | 120 | } 121 | -------------------------------------------------------------------------------- /libHttp/src/main/java/com/lzy/libhttp/result/BaseResult.java: -------------------------------------------------------------------------------- 1 | package com.lzy.libhttp.result; 2 | 3 | import java.io.Serializable; 4 | 5 | /** 6 | * @author: cyli8 7 | * @date: 2018/7/12 08:53 8 | */ 9 | public class BaseResult implements Serializable { 10 | private static final long serialVersionUID = 6457384685712227871L; 11 | 12 | } 13 | -------------------------------------------------------------------------------- /libHttp/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | libHttp 3 | 4 | -------------------------------------------------------------------------------- /libUtils/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /libUtils/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | 3 | android { 4 | compileSdkVersion rootProject.ext.compileSdkVersion 5 | 6 | defaultConfig { 7 | minSdkVersion rootProject.ext.minSdkVersion 8 | targetSdkVersion rootProject.ext.targetSdkVersion 9 | versionCode 1 10 | versionName "1.0" 11 | 12 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 13 | 14 | } 15 | 16 | buildTypes { 17 | release { 18 | minifyEnabled true 19 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 20 | } 21 | } 22 | 23 | resourcePrefix "lib_utils_" 24 | 25 | } 26 | 27 | dependencies { 28 | implementation fileTree(dir: 'libs', include: ['*.jar']) 29 | api 'com.alibaba:fastjson:1.1.67.android' 30 | api 'com.orhanobut:logger:2.1.1' 31 | implementation 'androidx.annotation:annotation:1.1.0' 32 | } 33 | -------------------------------------------------------------------------------- /libUtils/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | 23 | # FastJson 24 | -dontwarn com.alibaba.fastjson.** 25 | -keep class com.alibaba.fastjson.** { *; } 26 | -keepattributes Signature 27 | -keepattributes *Annotation* -------------------------------------------------------------------------------- /libUtils/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /libUtils/src/main/java/com/lzy/utils/CommonExecuter.java: -------------------------------------------------------------------------------- 1 | package com.lzy.utils; 2 | 3 | import android.os.Handler; 4 | import android.os.Looper; 5 | import android.util.Log; 6 | 7 | import java.util.ArrayList; 8 | import java.util.List; 9 | import java.util.concurrent.Executor; 10 | import java.util.concurrent.LinkedBlockingQueue; 11 | import java.util.concurrent.ThreadPoolExecutor; 12 | import java.util.concurrent.TimeUnit; 13 | 14 | /** 15 | * 公用的线程池 16 | * 17 | * @author: cyli8 18 | * @date: 2018/2/23 09:14 19 | */ 20 | 21 | public class CommonExecuter { 22 | public interface OnExecuteCompleteListener { 23 | void onExecuteComplete(); 24 | } 25 | 26 | private class CommonRunnable implements Runnable { 27 | private List mRunnable; 28 | private OnExecuteCompleteListener mListener; 29 | 30 | public CommonRunnable(Runnable r, OnExecuteCompleteListener l) { 31 | mRunnable = new ArrayList(); 32 | mRunnable.add(r); 33 | mListener = l; 34 | } 35 | 36 | public CommonRunnable(OnExecuteCompleteListener l, Runnable... rs) { 37 | mRunnable = new ArrayList(); 38 | for (Runnable r : rs) { 39 | if (null != r) { 40 | mRunnable.add(r); 41 | } 42 | } 43 | mListener = l; 44 | } 45 | 46 | @Override 47 | public void run() { 48 | if (ListUtil.isEmpty(mRunnable)) { 49 | return; 50 | } 51 | Log.i("CommonExecuter", "running task begin ..."); 52 | for (Runnable r : mRunnable) { 53 | r.run(); 54 | } 55 | Log.i("CommonExecuter", "running task end, and post the result"); 56 | if (null == mListener) { 57 | return; 58 | } 59 | mHandler.post(new Runnable() { 60 | @Override 61 | public void run() { 62 | mListener.onExecuteComplete(); 63 | } 64 | }); 65 | } 66 | } 67 | 68 | private static CommonExecuter mInstance = null; 69 | private static final int CORE_THREAD_COUNT = 5; 70 | 71 | private Executor mExecutor; 72 | private Handler mHandler = new Handler(Looper.getMainLooper()); 73 | 74 | private CommonExecuter() { 75 | mExecutor = new ThreadPoolExecutor(CORE_THREAD_COUNT, CORE_THREAD_COUNT, 76 | 10L, TimeUnit.MILLISECONDS, 77 | new LinkedBlockingQueue()); 78 | } 79 | 80 | public Executor getExecutor() { 81 | return mExecutor; 82 | } 83 | 84 | public static CommonExecuter getInstance() { 85 | if (null == mInstance) { 86 | synchronized (CommonExecuter.class) { 87 | if (null == mInstance) { 88 | mInstance = new CommonExecuter(); 89 | } 90 | } 91 | } 92 | return mInstance; 93 | } 94 | 95 | public static void run(Runnable runnable) { 96 | run(runnable, null); 97 | } 98 | 99 | public static void run(Runnable r, OnExecuteCompleteListener l) { 100 | getInstance().mExecutor.execute(mInstance.new CommonRunnable(r, l)); 101 | } 102 | 103 | public static void run(Runnable... r) { 104 | run(null, r); 105 | } 106 | 107 | public static void run(OnExecuteCompleteListener l, Runnable... r) { 108 | getInstance().mExecutor.execute(mInstance.new CommonRunnable(l, r)); 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /libUtils/src/main/java/com/lzy/utils/DisplayUtil.java: -------------------------------------------------------------------------------- 1 | package com.lzy.utils; 2 | 3 | import android.content.Context; 4 | 5 | /** 6 | * dp、px、sp之间的转化类 7 | * 8 | * @author: cyli8 9 | * @date: 2018/2/11 16:24 10 | */ 11 | 12 | public class DisplayUtil { 13 | /** 14 | * dp 转 px 15 | * 16 | * @param dpValue dp 值 17 | * @return px 值 18 | */ 19 | public static int dp2px(Context context, float dpValue) { 20 | final float scale = context.getResources().getDisplayMetrics().density; 21 | return (int) (dpValue * scale + 0.5f); 22 | } 23 | 24 | /** 25 | * px 转 dp 26 | * 27 | * @param pxValue px 值 28 | * @return dp 值 29 | */ 30 | public static int px2dp(Context context, float pxValue) { 31 | final float scale = context.getResources().getDisplayMetrics().density; 32 | return (int) (pxValue / scale + 0.5f); 33 | } 34 | 35 | /** 36 | * sp 转 px 37 | * 38 | * @param spValue sp 值 39 | * @return px 值 40 | */ 41 | public static int sp2px(Context context, float spValue) { 42 | final float fontScale = context.getResources().getDisplayMetrics().scaledDensity; 43 | return (int) (spValue * fontScale + 0.5f); 44 | } 45 | 46 | /** 47 | * px 转 sp 48 | * 49 | * @param pxValue px 值 50 | * @return sp 值 51 | */ 52 | public static int px2sp(Context context, float pxValue) { 53 | final float fontScale = context.getResources().getDisplayMetrics().scaledDensity; 54 | return (int) (pxValue / fontScale + 0.5f); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /libUtils/src/main/java/com/lzy/utils/IntentUtil.java: -------------------------------------------------------------------------------- 1 | package com.lzy.utils; 2 | 3 | import android.content.Context; 4 | import android.content.Intent; 5 | import android.content.pm.PackageManager; 6 | import android.content.pm.ResolveInfo; 7 | 8 | /** 9 | * Intent相关工具类 10 | * 11 | * @author: cyli8 12 | * @date: 2018/3/2 11:03 13 | */ 14 | 15 | public class IntentUtil { 16 | /** 17 | * 判断当前activity是否可跳转 18 | * 19 | * @param context 20 | * @param intent 21 | * @return 22 | */ 23 | public static boolean isActivityCanJump(Context context, Intent intent) { 24 | if (null == intent) return false; 25 | ResolveInfo resolveInfo = context.getPackageManager().resolveActivity(intent, PackageManager.MATCH_DEFAULT_ONLY); 26 | if (resolveInfo != null && resolveInfo.activityInfo != null) { 27 | return resolveInfo.activityInfo.exported; 28 | } 29 | return false; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /libUtils/src/main/java/com/lzy/utils/JsonUtil.java: -------------------------------------------------------------------------------- 1 | package com.lzy.utils; 2 | 3 | import android.text.TextUtils; 4 | 5 | import com.alibaba.fastjson.JSON; 6 | import com.alibaba.fastjson.JSONObject; 7 | 8 | import java.util.List; 9 | 10 | /** 11 | * json序列化和反序列化工具类,基于fastjson库 12 | * 13 | * @author: cyli8 14 | * @date: 2018/2/11 16:50 15 | */ 16 | 17 | public class JsonUtil { 18 | /** 19 | * 将对象序列化成JSON字符串 20 | * 21 | * @param obj 22 | * @return json类型字符串 23 | */ 24 | public static String toJSONString(Object obj) { 25 | return JSONObject.toJSONString(obj); 26 | } 27 | 28 | /** 29 | * 将JSON字符串反序列化成对象 30 | * 31 | * @param jsonStr 32 | * @param clazz 33 | * @param 34 | * @return 35 | */ 36 | public static T parseObject(String jsonStr, Class clazz) { 37 | try { 38 | if (!TextUtils.isEmpty(jsonStr)) { 39 | return JSON.parseObject(jsonStr, clazz); 40 | } 41 | } catch (Exception e) { 42 | e.printStackTrace(); 43 | } 44 | return null; 45 | } 46 | 47 | /** 48 | * 将JSON字符串反序列化成List 49 | * 50 | * @param jsonStr 51 | * @param clazz 52 | * @param 53 | * @return 54 | */ 55 | public static List parseArray(String jsonStr, Class clazz) { 56 | try { 57 | if (!TextUtils.isEmpty(jsonStr)) { 58 | return JSON.parseArray(jsonStr, clazz); 59 | } 60 | } catch (Exception e) { 61 | e.printStackTrace(); 62 | } 63 | return null; 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /libUtils/src/main/java/com/lzy/utils/ListUtil.java: -------------------------------------------------------------------------------- 1 | package com.lzy.utils; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | import java.util.Map; 6 | import java.util.Set; 7 | 8 | /** 9 | * list工具类 10 | * 11 | * @author: cyli8 12 | * @date: 2018/2/23 09:15 13 | */ 14 | 15 | public class ListUtil { 16 | public static int size(List list) { 17 | return null == list ? 0 : list.size(); 18 | } 19 | 20 | public static boolean isIndexValid(List list, int index) { 21 | if (null == list) { 22 | return false; 23 | } 24 | return index >= 0 && index < list.size(); 25 | } 26 | 27 | public static int size(List... lists) { 28 | int count = 0; 29 | for (List l : lists) { 30 | count += size(l); 31 | } 32 | return count; 33 | } 34 | 35 | public static int size(T... list) { 36 | return null == list ? 0 : list.length; 37 | } 38 | 39 | public static boolean isEmpty(List list) { 40 | if (null == list) { 41 | return true; 42 | } 43 | return list.isEmpty(); 44 | } 45 | 46 | public static boolean isEmpty(List... lists) { 47 | if (null == lists) { 48 | return true; 49 | } 50 | for (List l : lists) { 51 | if (isNotEmpty(l)) { 52 | return false; 53 | } 54 | } 55 | return true; 56 | } 57 | 58 | public static boolean isEmpty(T[] list) { 59 | if (null == list) { 60 | return true; 61 | } 62 | return list.length == 0; 63 | } 64 | 65 | public static boolean isNotEmpty(List list) { 66 | return !isEmpty(list); 67 | } 68 | 69 | public static boolean isNotEmpty(T[] list) { 70 | return !isEmpty(list); 71 | } 72 | 73 | public static boolean isNotEmpty(Map map) { 74 | if (null != map && map.size() > 0) { 75 | return true; 76 | } 77 | return false; 78 | } 79 | 80 | public static boolean isNotEmpty(Set map) { 81 | if (null != map && map.size() > 0) { 82 | return true; 83 | } 84 | return false; 85 | } 86 | 87 | public static boolean isEmpty2(T... list) { 88 | return list == null || list.length == 0; 89 | } 90 | 91 | public static boolean isNotEmpty2(T... list) { 92 | return !isEmpty2(list); 93 | } 94 | 95 | public static T getItem(List list, int pos) { 96 | if (null == list) { 97 | return null; 98 | } 99 | int size = list.size(); 100 | if (pos < 0 || pos >= size) { 101 | return null; 102 | } 103 | return list.get(pos); 104 | } 105 | 106 | public static boolean contains(T[] list, T item) { 107 | for (T i : list) { 108 | if (i == item || i.equals(item)) { 109 | return true; 110 | } 111 | } 112 | return false; 113 | } 114 | 115 | public static boolean indexIn(List list, int index) { 116 | if (null == list) { 117 | return false; 118 | } 119 | return index >= 0 && index < list.size(); 120 | } 121 | 122 | public static List copy(List arr) { 123 | int size = ListUtil.size(arr); 124 | ArrayList ret = new ArrayList<>(size); 125 | if (size > 0) { 126 | ret.addAll(arr); 127 | } 128 | return ret; 129 | } 130 | 131 | public static List newList(List list) { 132 | if (null == list) { 133 | return new ArrayList(); 134 | } else { 135 | list.clear(); 136 | return list; 137 | } 138 | } 139 | } 140 | -------------------------------------------------------------------------------- /libUtils/src/main/java/com/lzy/utils/SharedPreferencesUtil.java: -------------------------------------------------------------------------------- 1 | package com.lzy.utils; 2 | 3 | import android.content.Context; 4 | import android.content.SharedPreferences; 5 | 6 | import androidx.annotation.NonNull; 7 | 8 | import java.util.Collections; 9 | import java.util.Map; 10 | import java.util.Set; 11 | 12 | /** 13 | * 共享偏好工具类 14 | * 15 | * @author: cyli8 16 | * @date: 2017/9/22 16:56 17 | */ 18 | 19 | public class SharedPreferencesUtil { 20 | private SharedPreferences mSP; 21 | 22 | public static final String DEFAULT_SP_NAME = "fastdevelop_sp"; 23 | 24 | public SharedPreferencesUtil(Context context) { 25 | mSP = context.getSharedPreferences(DEFAULT_SP_NAME, Context.MODE_PRIVATE); 26 | } 27 | 28 | public SharedPreferencesUtil(Context context, String spName) { 29 | mSP = context.getSharedPreferences(spName, Context.MODE_PRIVATE); 30 | } 31 | 32 | public SharedPreferences getSp() { 33 | return mSP; 34 | } 35 | 36 | /** 37 | * SP中写入String 38 | * 39 | * @param key 键 40 | * @param value 值 41 | */ 42 | public void put(@NonNull final String key, @NonNull final String value) { 43 | put(key, value, false); 44 | } 45 | 46 | /** 47 | * SP中写入String 48 | * 49 | * @param key 键 50 | * @param value 值 51 | * @param isCommit {@code true}: {@link SharedPreferences.Editor#commit()} 52 | * {@code false}: {@link SharedPreferences.Editor#apply()} 53 | */ 54 | public boolean put(@NonNull String key, @NonNull String value, boolean isCommit) { 55 | if (isCommit) { 56 | return mSP.edit().putString(key, value).commit(); 57 | } else { 58 | mSP.edit().putString(key, value).apply(); 59 | return false; 60 | } 61 | } 62 | 63 | /** 64 | * SP中读取String 65 | * 66 | * @param key 键 67 | * @return 存在返回对应值,不存在返回默认值{@code ""} 68 | */ 69 | public String getString(@NonNull String key) { 70 | return getString(key, ""); 71 | } 72 | 73 | /** 74 | * SP中读取String 75 | * 76 | * @param key 键 77 | * @param defaultValue 默认值 78 | * @return 存在返回对应值,不存在返回默认值{@code defaultValue} 79 | */ 80 | public String getString(@NonNull String key, @NonNull String defaultValue) { 81 | return mSP.getString(key, defaultValue); 82 | } 83 | 84 | /** 85 | * SP中写入int 86 | * 87 | * @param key 键 88 | * @param value 值 89 | */ 90 | public void put(@NonNull String key, int value) { 91 | put(key, value, false); 92 | } 93 | 94 | /** 95 | * SP中写入int 96 | * 97 | * @param key 键 98 | * @param value 值 99 | * @param isCommit {@code true}: {@link SharedPreferences.Editor#commit()}
100 | * {@code false}: {@link SharedPreferences.Editor#apply()} 101 | */ 102 | public boolean put(@NonNull String key, final int value, final boolean isCommit) { 103 | if (isCommit) { 104 | return mSP.edit().putInt(key, value).commit(); 105 | } else { 106 | mSP.edit().putInt(key, value).apply(); 107 | return false; 108 | } 109 | } 110 | 111 | /** 112 | * SP中读取int 113 | * 114 | * @param key 键 115 | * @return 存在返回对应值,不存在返回默认值-1 116 | */ 117 | public int getInt(@NonNull String key) { 118 | return getInt(key, -1); 119 | } 120 | 121 | /** 122 | * SP中读取int 123 | * 124 | * @param key 键 125 | * @param defaultValue 默认值 126 | * @return 存在返回对应值,不存在返回默认值{@code defaultValue} 127 | */ 128 | public int getInt(@NonNull String key, int defaultValue) { 129 | return mSP.getInt(key, defaultValue); 130 | } 131 | 132 | /** 133 | * SP中写入long 134 | * 135 | * @param key 键 136 | * @param value 值 137 | */ 138 | public void put(@NonNull String key, long value) { 139 | put(key, value, false); 140 | } 141 | 142 | /** 143 | * SP中写入long 144 | * 145 | * @param key 键 146 | * @param value 值 147 | * @param isCommit {@code true}: {@link SharedPreferences.Editor#commit()}
148 | * {@code false}: {@link SharedPreferences.Editor#apply()} 149 | */ 150 | public boolean put(@NonNull String key, long value, boolean isCommit) { 151 | if (isCommit) { 152 | return mSP.edit().putLong(key, value).commit(); 153 | } else { 154 | mSP.edit().putLong(key, value).apply(); 155 | return false; 156 | } 157 | } 158 | 159 | /** 160 | * SP中读取long 161 | * 162 | * @param key 键 163 | * @return 存在返回对应值,不存在返回默认值-1 164 | */ 165 | public long getLong(@NonNull String key) { 166 | return getLong(key, -1L); 167 | } 168 | 169 | /** 170 | * SP中读取long 171 | * 172 | * @param key 键 173 | * @param defaultValue 默认值 174 | * @return 存在返回对应值,不存在返回默认值{@code defaultValue} 175 | */ 176 | public long getLong(@NonNull String key, long defaultValue) { 177 | return mSP.getLong(key, defaultValue); 178 | } 179 | 180 | /** 181 | * SP中写入float 182 | * 183 | * @param key 键 184 | * @param value 值 185 | */ 186 | public void put(@NonNull String key, float value) { 187 | put(key, value, false); 188 | } 189 | 190 | /** 191 | * SP中写入float 192 | * 193 | * @param key 键 194 | * @param value 值 195 | * @param isCommit {@code true}: {@link SharedPreferences.Editor#commit()}
196 | * {@code false}: {@link SharedPreferences.Editor#apply()} 197 | */ 198 | public boolean put(@NonNull final String key, final float value, final boolean isCommit) { 199 | if (isCommit) { 200 | return mSP.edit().putFloat(key, value).commit(); 201 | } else { 202 | mSP.edit().putFloat(key, value).apply(); 203 | return false; 204 | } 205 | } 206 | 207 | /** 208 | * SP中读取float 209 | * 210 | * @param key 键 211 | * @return 存在返回对应值,不存在返回默认值-1 212 | */ 213 | public float getFloat(@NonNull String key) { 214 | return getFloat(key, -1f); 215 | } 216 | 217 | /** 218 | * SP中读取float 219 | * 220 | * @param key 键 221 | * @param defaultValue 默认值 222 | * @return 存在返回对应值,不存在返回默认值{@code defaultValue} 223 | */ 224 | public float getFloat(@NonNull String key, float defaultValue) { 225 | return mSP.getFloat(key, defaultValue); 226 | } 227 | 228 | /** 229 | * SP中写入boolean 230 | * 231 | * @param key 键 232 | * @param value 值 233 | */ 234 | public void put(@NonNull final String key, boolean value) { 235 | put(key, value, false); 236 | } 237 | 238 | /** 239 | * SP中写入boolean 240 | * 241 | * @param key 键 242 | * @param value 值 243 | * @param isCommit {@code true}: {@link SharedPreferences.Editor#commit()}
244 | * {@code false}: {@link SharedPreferences.Editor#apply()} 245 | */ 246 | public boolean put(@NonNull String key, boolean value, boolean isCommit) { 247 | if (isCommit) { 248 | return mSP.edit().putBoolean(key, value).commit(); 249 | } else { 250 | mSP.edit().putBoolean(key, value).apply(); 251 | return false; 252 | } 253 | } 254 | 255 | /** 256 | * SP中读取boolean 257 | * 258 | * @param key 键 259 | * @return 存在返回对应值,不存在返回默认值{@code false} 260 | */ 261 | public boolean getBoolean(@NonNull String key) { 262 | return getBoolean(key, false); 263 | } 264 | 265 | /** 266 | * SP中读取boolean 267 | * 268 | * @param key 键 269 | * @param defaultValue 默认值 270 | * @return 存在返回对应值,不存在返回默认值{@code defaultValue} 271 | */ 272 | public boolean getBoolean(@NonNull String key, boolean defaultValue) { 273 | return mSP.getBoolean(key, defaultValue); 274 | } 275 | 276 | /** 277 | * SP中写入String集合 278 | * 279 | * @param key 键 280 | * @param values 值 281 | */ 282 | public void put(@NonNull String key, @NonNull Set values) { 283 | put(key, values, false); 284 | } 285 | 286 | /** 287 | * SP中写入String集合 288 | * 289 | * @param key 键 290 | * @param values 值 291 | * @param isCommit {@code true}: {@link SharedPreferences.Editor#commit()}
292 | * {@code false}: {@link SharedPreferences.Editor#apply()} 293 | */ 294 | public boolean put(@NonNull String key, @NonNull Set values, boolean isCommit) { 295 | if (isCommit) { 296 | return mSP.edit().putStringSet(key, values).commit(); 297 | } else { 298 | mSP.edit().putStringSet(key, values).apply(); 299 | return false; 300 | } 301 | } 302 | 303 | /** 304 | * SP中读取StringSet 305 | * 306 | * @param key 键 307 | * @return 存在返回对应值,不存在返回默认值{@link Collections#emptySet()} 308 | */ 309 | public Set getStringSet(@NonNull String key) { 310 | return getStringSet(key, Collections.emptySet()); 311 | } 312 | 313 | /** 314 | * SP中读取StringSet 315 | * 316 | * @param key 键 317 | * @param defaultValue 默认值 318 | * @return 存在返回对应值,不存在返回默认值{@code defaultValue} 319 | */ 320 | public Set getStringSet(@NonNull String key, @NonNull Set defaultValue) { 321 | return mSP.getStringSet(key, defaultValue); 322 | } 323 | 324 | /** 325 | * SP中获取所有键值对 326 | * 327 | * @return Map对象 328 | */ 329 | public Map getAll() { 330 | return mSP.getAll(); 331 | } 332 | 333 | /** 334 | * SP中是否存在该key 335 | * 336 | * @param key 键 337 | * @return {@code true}: 存在
{@code false}: 不存在 338 | */ 339 | public boolean contains(@NonNull String key) { 340 | return mSP.contains(key); 341 | } 342 | 343 | /** 344 | * SP中移除该key 345 | * 346 | * @param key 键 347 | */ 348 | public void remove(@NonNull String key) { 349 | remove(key, false); 350 | } 351 | 352 | /** 353 | * SP中移除该key 354 | * 355 | * @param key 键 356 | * @param isCommit {@code true}: {@link SharedPreferences.Editor#commit()}
357 | * {@code false}: {@link SharedPreferences.Editor#apply()} 358 | */ 359 | public boolean remove(@NonNull String key, boolean isCommit) { 360 | if (isCommit) { 361 | return mSP.edit().remove(key).commit(); 362 | } else { 363 | mSP.edit().remove(key).apply(); 364 | return false; 365 | } 366 | } 367 | 368 | /** 369 | * SP中清除所有数据 370 | */ 371 | public void clear() { 372 | clear(false); 373 | } 374 | 375 | /** 376 | * SP中清除所有数据 377 | * 378 | * @param isCommit {@code true}: {@link SharedPreferences.Editor#commit()}
379 | * {@code false}: {@link SharedPreferences.Editor#apply()} 380 | */ 381 | public boolean clear(boolean isCommit) { 382 | if (isCommit) { 383 | return mSP.edit().clear().commit(); 384 | } else { 385 | mSP.edit().clear().apply(); 386 | return false; 387 | } 388 | } 389 | 390 | } 391 | -------------------------------------------------------------------------------- /libUtils/src/main/java/com/lzy/utils/SoftInputManager.java: -------------------------------------------------------------------------------- 1 | package com.lzy.utils; 2 | 3 | import android.content.Context; 4 | import android.view.inputmethod.InputMethodManager; 5 | import android.widget.EditText; 6 | 7 | import java.util.Timer; 8 | import java.util.TimerTask; 9 | 10 | public class SoftInputManager { 11 | 12 | /** 13 | * 弹出软键盘,有些手机不能及时弹出,故用该延时方式 14 | * 15 | * @param context 16 | */ 17 | public static void showSoftInput(final Context context) { 18 | final Timer timer = new Timer(); 19 | TimerTask task = new TimerTask() { 20 | @Override 21 | public void run() { 22 | InputMethodManager imm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE); 23 | imm.toggleSoftInput(0, InputMethodManager.HIDE_NOT_ALWAYS); 24 | cancel(); 25 | timer.cancel(); 26 | } 27 | }; 28 | timer.schedule(task, 800); 29 | } 30 | 31 | /** 32 | * 弹出软键盘 33 | * 34 | * @param context 35 | * @param view 36 | */ 37 | public static void showSoftInput(Context context, EditText view) { 38 | if (context != null && view != null) { 39 | InputMethodManager inputManager = (InputMethodManager) view 40 | .getContext().getSystemService( 41 | Context.INPUT_METHOD_SERVICE); 42 | inputManager.showSoftInput(view, 0); 43 | } 44 | } 45 | 46 | /** 47 | * 显示或者隐藏输入法 48 | * 49 | * @param context 50 | */ 51 | @Deprecated 52 | public static void hideSoftInput(Context context) { 53 | InputMethodManager imm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE); 54 | imm.toggleSoftInput(0, InputMethodManager.HIDE_NOT_ALWAYS); 55 | } 56 | 57 | public static boolean hideSoftInput(final EditText e) { 58 | InputMethodManager inputManager = (InputMethodManager) e 59 | .getContext().getSystemService( 60 | Context.INPUT_METHOD_SERVICE); 61 | return inputManager.hideSoftInputFromWindow(e.getWindowToken(), 0); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /libUtils/src/main/java/com/lzy/utils/StringUtil.java: -------------------------------------------------------------------------------- 1 | package com.lzy.utils; 2 | 3 | /** 4 | * 字符串工具类 5 | * 6 | * @author: cyli8 7 | * @date: 2018/2/11 17:10 8 | */ 9 | 10 | public class StringUtil { 11 | /** 12 | * 判断字符串是否为 null 或长度为 0 13 | * 14 | * @param s 待校验字符串 15 | * @return {@code true}: 空
{@code false}: 不为空 16 | */ 17 | public static boolean isEmpty(final CharSequence s) { 18 | return s == null || s.length() == 0; 19 | } 20 | 21 | /** 22 | * 判断字符串是否为 null 或全为空格 23 | * 24 | * @param s 待校验字符串 25 | * @return {@code true}: null 或全空格
{@code false}: 不为 null 且不全空格 26 | */ 27 | public static boolean isTrimEmpty(final CharSequence s) { 28 | return (s == null || s.toString().trim().length() == 0); 29 | } 30 | 31 | /** 32 | * 判断两字符串是否相等 33 | * 34 | * @param a 待校验字符串 a 35 | * @param b 待校验字符串 b 36 | * @return {@code true}: 相等
{@code false}: 不相等 37 | */ 38 | public static boolean equals(final CharSequence a, final CharSequence b) { 39 | if (a == b) return true; 40 | int length; 41 | if (a != null && b != null && (length = a.length()) == b.length()) { 42 | if (a instanceof String && b instanceof String) { 43 | return a.equals(b); 44 | } else { 45 | for (int i = 0; i < length; i++) { 46 | if (a.charAt(i) != b.charAt(i)) return false; 47 | } 48 | return true; 49 | } 50 | } 51 | return false; 52 | } 53 | 54 | /** 55 | * 判断两字符串忽略大小写是否相等 56 | * 57 | * @param a 待校验字符串 a 58 | * @param b 待校验字符串 b 59 | * @return {@code true}: 相等
{@code false}: 不相等 60 | */ 61 | public static boolean equalsIgnoreCase(final String a, final String b) { 62 | return a == null ? b == null : a.equalsIgnoreCase(b); 63 | } 64 | } 65 | 66 | -------------------------------------------------------------------------------- /libUtils/src/main/java/com/lzy/utils/SystemActivityUtil.java: -------------------------------------------------------------------------------- 1 | package com.lzy.utils; 2 | 3 | import android.content.Context; 4 | import android.content.Intent; 5 | import android.net.Uri; 6 | 7 | /** 8 | * 跳转到系统页面工具类 9 | * 10 | * @author: cyli8 11 | * @date: 2018/2/11 16:55 12 | */ 13 | 14 | public class SystemActivityUtil { 15 | /*** 16 | * 打开浏览器,用户选择使用哪个浏览器 17 | */ 18 | public static final void callBrowser(Context c, String url) { 19 | callBrower(c, url, null, null); 20 | } 21 | 22 | private static final void callBrower(Context c, String url, String packName, String activityName) { 23 | String httpUrl = url; 24 | int index = httpUrl.indexOf("http://"); 25 | if (index < 0) { 26 | index = httpUrl.indexOf("https://"); 27 | } 28 | if (index < 0) { 29 | httpUrl = "http://" + url; 30 | } 31 | Intent intent = new Intent(); 32 | intent.setAction("android.intent.action.VIEW"); 33 | intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 34 | Uri content_url = Uri.parse(httpUrl); 35 | intent.setData(content_url); 36 | if (null != packName && null != activityName) { 37 | intent.setClassName(packName, activityName); 38 | } 39 | c.startActivity(intent); 40 | } 41 | 42 | /** 43 | * 跳至拨号界面 44 | * 45 | * @param phoneNumber 电话号码 46 | */ 47 | public static void dialPhone(Context context, String phoneNumber) { 48 | Intent intent = new Intent("android.intent.action.DIAL", Uri.parse("tel:" + phoneNumber)); 49 | context.startActivity(intent); 50 | } 51 | 52 | /** 53 | * 拨打电话 54 | *

需添加权限 {@code }

55 | * 56 | * @param phoneNumber 电话号码 57 | */ 58 | public static void callPhone(Context context, String phoneNumber) { 59 | Intent intent = new Intent("android.intent.action.CALL", Uri.parse("tel:" + phoneNumber)); 60 | context.startActivity(intent); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /libUtils/src/main/java/com/lzy/utils/TimeUtil.java: -------------------------------------------------------------------------------- 1 | package com.lzy.utils; 2 | 3 | import java.text.ParseException; 4 | import java.text.SimpleDateFormat; 5 | import java.util.Date; 6 | import java.util.Locale; 7 | 8 | /** 9 | * 时间工具类 10 | * 11 | * @author: cyli8 12 | * @date: 2018/3/8 09:18 13 | */ 14 | 15 | public class TimeUtil { 16 | public static String getYMDHms(long t) { 17 | return getSpecialFormatTime("yyyy-MM-dd HH:mm:ss", t); 18 | } 19 | 20 | public static String getSpecialFormatTime(String pattern, long time) { 21 | SimpleDateFormat format = new SimpleDateFormat(pattern, Locale.getDefault()); 22 | Date currentTime = new Date(time); 23 | return format.format(currentTime); 24 | } 25 | 26 | public static long formatTimeToMillis(String timeType, String time) { 27 | SimpleDateFormat format = new SimpleDateFormat(timeType, Locale.CHINA); 28 | try { 29 | Date date = format.parse(time); 30 | return date.getTime(); 31 | } catch (ParseException e) { 32 | return 0; 33 | } 34 | } 35 | 36 | public static boolean isCurDate(long lastTime) { 37 | long timeMillis = System.currentTimeMillis(); 38 | SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd", Locale.CHINA); 39 | String sp_time = sf.format(lastTime); 40 | String current_time = sf.format(timeMillis); 41 | return sp_time.equals(current_time); 42 | } 43 | 44 | /** 45 | * 某时间点和现在时间对比 46 | */ 47 | public static boolean isFuture(long compareTime) { 48 | return compareTime > System.currentTimeMillis(); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /libUtils/src/main/java/com/lzy/utils/encrypt/MD5Util.java: -------------------------------------------------------------------------------- 1 | package com.lzy.utils.encrypt; 2 | 3 | import android.text.TextUtils; 4 | 5 | import java.io.FileInputStream; 6 | import java.io.InputStream; 7 | import java.security.MessageDigest; 8 | 9 | /** 10 | * md5加密工具类 11 | * 12 | * @author: cyli8 13 | * @date: 2018/2/11 17:17 14 | */ 15 | 16 | public class MD5Util { 17 | private static final char hexDigits[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 18 | 'a', 'b', 'c', 'd', 'e', 'f'}; 19 | 20 | public final static String md5Encode(final String s) { 21 | if (TextUtils.isEmpty(s)) { 22 | return ""; 23 | } 24 | try { 25 | final byte[] strTemp = s.getBytes(); 26 | final MessageDigest mdTemp = MessageDigest.getInstance("MD5"); 27 | mdTemp.update(strTemp); 28 | final byte[] md = mdTemp.digest(); 29 | final int j = md.length; 30 | final char str[] = new char[j * 2]; 31 | int k = 0; 32 | for (int i = 0; i < j; i++) { 33 | final byte byte0 = md[i]; 34 | str[k++] = hexDigits[byte0 >>> 4 & 0xf]; 35 | str[k++] = hexDigits[byte0 & 0xf]; 36 | } 37 | return new String(str); 38 | } catch (Exception e) { 39 | return null; 40 | } 41 | } 42 | 43 | public final static String md5Encode(final byte[] md) { 44 | try { 45 | final int j = md.length; 46 | final char str[] = new char[j * 2]; 47 | int k = 0; 48 | for (int i = 0; i < j; i++) { 49 | final byte byte0 = md[i]; 50 | str[k++] = hexDigits[byte0 >>> 4 & 0xf]; 51 | str[k++] = hexDigits[byte0 & 0xf]; 52 | } 53 | return new String(str); 54 | } catch (Exception e) { 55 | return null; 56 | } 57 | } 58 | 59 | private static final String toHexString(final byte[] b) { 60 | final StringBuilder sb = new StringBuilder(b.length * 2); 61 | for (int i = 0; i < b.length; i++) { 62 | final byte byte0 = b[i]; 63 | sb.append(hexDigits[byte0 >>> 4 & 0xf]); 64 | sb.append(hexDigits[byte0 & 0x0f]); 65 | } 66 | return sb.toString(); 67 | } 68 | 69 | /** 70 | * 求一个文件的MD5签名 71 | * 72 | * @return 73 | */ 74 | public final static String md5EncodeFile(final String fileName) { 75 | final byte[] buffer = new byte[1024]; 76 | int bytes; 77 | MessageDigest md5; 78 | try { 79 | final InputStream is = new FileInputStream(fileName); 80 | md5 = MessageDigest.getInstance("MD5"); 81 | while ((bytes = is.read(buffer)) > 0) { 82 | md5.update(buffer, 0, bytes); 83 | } 84 | is.close(); 85 | return toHexString(md5.digest()); 86 | } catch (Exception e) { 87 | return null; 88 | } 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /libUtils/src/main/java/com/lzy/utils/file/FileUtil.java: -------------------------------------------------------------------------------- 1 | package com.lzy.utils.file; 2 | 3 | import android.os.Environment; 4 | 5 | import java.io.File; 6 | 7 | /** 8 | * 操作文件工具类 9 | * 10 | * @author: cyli8 11 | * @date: 2018/2/11 16:15 12 | */ 13 | 14 | public class FileUtil { 15 | public static boolean isExternalStorageAvailable() { 16 | return Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState()); 17 | } 18 | 19 | /** 20 | * 删除指定文件夹下所有文件 21 | * 22 | * @param path 文件夹完整绝对路径 23 | * @return 24 | */ 25 | public static boolean delAllFile(String path) { 26 | boolean flag = false; 27 | File file = new File(path); 28 | if (!file.exists() || !file.isDirectory()) { 29 | return flag; 30 | } 31 | 32 | String[] tempList = file.list(); 33 | if (tempList == null || tempList.length == 0) { 34 | flag = true; 35 | return flag; 36 | } 37 | File temp = null; 38 | for (int i = 0; i < tempList.length; i++) { 39 | if (path.endsWith(File.separator)) { 40 | temp = new File(path + tempList[i]); 41 | } else { 42 | temp = new File(path + File.separator + tempList[i]); 43 | } 44 | if (temp.isFile()) { 45 | temp.delete(); 46 | } 47 | if (temp.isDirectory()) { 48 | delAllFile(path + "/" + tempList[i]);// 先删除文件夹里面的文件 49 | delFolder(path + "/" + tempList[i]);// 再删除空文件夹 50 | flag = true; 51 | } 52 | } 53 | return flag; 54 | } 55 | 56 | // 删除文件中的所有文件 57 | public static void delFolder(String folderPath) { 58 | try { 59 | delAllFile(folderPath); // 删除完里面所有内容 60 | File myFilePath = new File(folderPath); 61 | myFilePath.delete(); // 删除空文件夹 62 | } catch (Exception e) { 63 | e.printStackTrace(); 64 | } 65 | } 66 | 67 | /** 68 | * 删除某个指定的文件 69 | */ 70 | public static void delFile(String filePath) { 71 | File file = new File(filePath); 72 | if (file.exists()) { 73 | file.delete(); 74 | } 75 | } 76 | 77 | /** 78 | * 确保目录存在,不存在则创建 79 | * 80 | * @param dir 81 | * @return 82 | */ 83 | public static boolean ensureDirExist(String dir) { 84 | File f = new File(dir); 85 | if (f.exists()) { 86 | if (!f.isDirectory()) { 87 | f.delete(); 88 | } else { 89 | return true; 90 | } 91 | } 92 | boolean b = f.mkdirs(); 93 | return b; 94 | } 95 | 96 | /** 97 | * 递归获取文件或目录下文件大小 98 | * 99 | * @param file 目录 100 | * @return 字节大小 101 | */ 102 | public static long getDirSize(File file) { 103 | if (file.exists()) { 104 | if (file.isDirectory()) { 105 | File[] children = file.listFiles(); 106 | long size = 0; 107 | for (File f : children) 108 | size += getDirSize(f); 109 | return size; 110 | } else { 111 | return file.length(); 112 | } 113 | } else { 114 | return 0; 115 | } 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /libUtils/src/main/java/com/lzy/utils/log/MLog.java: -------------------------------------------------------------------------------- 1 | package com.lzy.utils.log; 2 | 3 | import com.orhanobut.logger.AndroidLogAdapter; 4 | import com.orhanobut.logger.CsvFormatStrategy; 5 | import com.orhanobut.logger.DiskLogAdapter; 6 | import com.orhanobut.logger.FormatStrategy; 7 | import com.orhanobut.logger.Logger; 8 | import com.orhanobut.logger.PrettyFormatStrategy; 9 | 10 | 11 | /** 12 | * 日志初始化类,基于Logger 13 | * 14 | * @author: cyli8 15 | * @date: 2018/2/11 17:20 16 | */ 17 | 18 | public class MLog { 19 | 20 | public static void initLogger(String defaultTAG, final boolean logAble) { 21 | FormatStrategy formatStrategy = PrettyFormatStrategy.newBuilder() 22 | .showThreadInfo(false) // (Optional) Whether to show thread info or not. Default true 23 | .methodCount(0) // (Optional) How many method line to show. Default 2 24 | .methodOffset(0) // (Optional) Hides internal method calls up to offset. Default 0 25 | // .logStrategy(customLog) // (Optional) Changes the log strategy to print out. Default LogCat 26 | .tag(defaultTAG) // (Optional) Global tag for every log. Default PRETTY_LOGGER 27 | .build(); 28 | Logger.addLogAdapter(new AndroidLogAdapter(formatStrategy) { 29 | @Override 30 | public boolean isLoggable(int priority, String tag) { 31 | return logAble; 32 | } 33 | }); 34 | 35 | FormatStrategy fileformatStrategy = CsvFormatStrategy.newBuilder() 36 | .tag(defaultTAG) 37 | .build(); 38 | Logger.addLogAdapter(new DiskLogAdapter(fileformatStrategy) { 39 | @Override 40 | public boolean isLoggable(int priority, String tag) { 41 | return logAble; 42 | } 43 | }); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /libUtils/src/main/java/com/lzy/utils/network/NetWorkUtil.java: -------------------------------------------------------------------------------- 1 | package com.lzy.utils.network; 2 | 3 | import android.content.Context; 4 | import android.net.ConnectivityManager; 5 | import android.net.NetworkInfo; 6 | 7 | public class NetWorkUtil { 8 | 9 | public static final int TYPE_WIFI = 1, TYPE_MOBILE = 0, TYPE_NONE = -1; 10 | 11 | /** 12 | * 检查网络是否可用 13 | * 14 | * @param context 15 | * @return 16 | */ 17 | public static boolean checkNetwork(Context context) { 18 | ConnectivityManager connectivityManager = (ConnectivityManager) context 19 | .getSystemService(Context.CONNECTIVITY_SERVICE); 20 | NetworkInfo activeNetInfo = connectivityManager 21 | .getNetworkInfo(ConnectivityManager.TYPE_WIFI); 22 | if (activeNetInfo != null && activeNetInfo.isConnected()) { 23 | return true; 24 | } 25 | activeNetInfo = connectivityManager 26 | .getNetworkInfo(ConnectivityManager.TYPE_MOBILE); 27 | return activeNetInfo != null && activeNetInfo.isConnected(); 28 | } 29 | 30 | 31 | public static int getNetWorkType(Context context) { 32 | ConnectivityManager connectivityManager = (ConnectivityManager) context 33 | .getSystemService(Context.CONNECTIVITY_SERVICE); 34 | NetworkInfo activeNetInfo = connectivityManager 35 | .getNetworkInfo(ConnectivityManager.TYPE_WIFI); 36 | if (activeNetInfo != null && activeNetInfo.isConnected()) { 37 | return TYPE_WIFI; 38 | } 39 | activeNetInfo = connectivityManager 40 | .getNetworkInfo(ConnectivityManager.TYPE_MOBILE); 41 | if (activeNetInfo != null && activeNetInfo.isConnected()) { 42 | return TYPE_MOBILE; 43 | } 44 | return TYPE_NONE; 45 | } 46 | 47 | } 48 | 49 | -------------------------------------------------------------------------------- /libUtils/src/main/java/com/lzy/utils/statusbar/StatusBarUtil.java: -------------------------------------------------------------------------------- 1 | package com.lzy.utils.statusbar; 2 | 3 | import android.app.Activity; 4 | import android.content.Context; 5 | import android.graphics.Color; 6 | import android.os.Build; 7 | import android.view.View; 8 | import android.view.Window; 9 | import android.view.WindowManager; 10 | 11 | /** 12 | * 状态栏工具类(状态栏颜色、沉浸、高度等) 13 | * 14 | * @author: cyli8 15 | * @date: 2018/7/24 15:48 16 | */ 17 | public class StatusBarUtil { 18 | 19 | public static void transparentStatus(Activity activity) { 20 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { 21 | Window window = activity.getWindow(); 22 | window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); 23 | window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN 24 | | View.SYSTEM_UI_FLAG_LAYOUT_STABLE); 25 | window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS); 26 | window.setStatusBarColor(Color.TRANSPARENT); 27 | } 28 | } 29 | 30 | /** 31 | * 设置状态栏颜色 32 | */ 33 | public static void setStatusBarColor(Activity activity, int color) { 34 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { 35 | Window window = activity.getWindow(); 36 | window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); 37 | window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS); 38 | window.setStatusBarColor(color); 39 | } 40 | } 41 | 42 | /** 43 | * 在Activity的onWindowFocusChanged()方法调用,实现游戏那种全屏沉浸模式 44 | */ 45 | public static void HideStatusAndNavigation(Activity activity) { 46 | View decorView = activity.getWindow().getDecorView(); 47 | decorView.setSystemUiVisibility( 48 | View.SYSTEM_UI_FLAG_LAYOUT_STABLE 49 | | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION 50 | | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN 51 | | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION 52 | | View.SYSTEM_UI_FLAG_FULLSCREEN 53 | | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY); 54 | } 55 | 56 | /** 57 | * 获取状态栏的高度 58 | */ 59 | public static int getStatusBarHeight(Context context) { 60 | int statusBarHeight = 54;//默认值 61 | if (context != null) { 62 | //获取status_bar_height资源的ID 63 | int resourceId = context.getResources().getIdentifier("status_bar_height", "dimen", "android"); 64 | if (resourceId > 0) { 65 | statusBarHeight = context.getResources().getDimensionPixelSize(resourceId); 66 | } 67 | } 68 | return statusBarHeight; 69 | } 70 | 71 | 72 | } 73 | -------------------------------------------------------------------------------- /libUtils/src/main/java/com/lzy/utils/system/ClipboardUtil.java: -------------------------------------------------------------------------------- 1 | package com.lzy.utils.system; 2 | 3 | import android.content.ClipData; 4 | import android.content.ClipboardManager; 5 | import android.content.Context; 6 | 7 | /** 8 | * 复制粘贴工具类 9 | * 10 | * @author: cyli8 11 | * @date: 2018/2/11 17:25 12 | */ 13 | 14 | public class ClipboardUtil { 15 | public static void copyText(Context context, String text) { 16 | ClipboardManager clipboardManager = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE); 17 | if (clipboardManager != null) { 18 | clipboardManager.setPrimaryClip(ClipData.newPlainText("simple text copy", text)); 19 | } 20 | } 21 | 22 | public static String getText(Context context) { 23 | ClipboardManager clipboardManager = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE); 24 | //判断剪贴板里是否有内容 25 | if (clipboardManager == null || !clipboardManager.hasPrimaryClip()) { 26 | return null; 27 | } 28 | ClipData clip = clipboardManager.getPrimaryClip(); 29 | return clip.getItemAt(0).getText().toString(); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /libUtils/src/main/java/com/lzy/utils/system/DeviceUtil.java: -------------------------------------------------------------------------------- 1 | package com.lzy.utils.system; 2 | 3 | import android.annotation.SuppressLint; 4 | import android.content.Context; 5 | import android.net.wifi.WifiInfo; 6 | import android.net.wifi.WifiManager; 7 | import android.os.Build; 8 | import android.provider.Settings; 9 | import android.telephony.TelephonyManager; 10 | 11 | /** 12 | * 获取手机mac地址等工具类 13 | * 14 | * @author: cyli8 15 | * @date: 2018/2/11 16:40 16 | */ 17 | 18 | public class DeviceUtil { 19 | /** 20 | * 获取设备 AndroidID 21 | * 22 | * @return AndroidID 23 | */ 24 | @SuppressLint("HardwareIds") 25 | public static String getAndroidID(Context context) { 26 | return Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ANDROID_ID); 27 | } 28 | 29 | /** 30 | * 获取设备 MAC 地址 31 | *

需添加权限 {@code }

32 | * 33 | * @return MAC 地址 34 | */ 35 | @SuppressLint({"HardwareIds", "MissingPermission"}) 36 | public static String getMacAddress(Context context) { 37 | try { 38 | @SuppressLint("WifiManagerLeak") 39 | WifiManager wifi = (WifiManager) context.getApplicationContext().getSystemService(Context.WIFI_SERVICE); 40 | if (wifi != null) { 41 | WifiInfo info = wifi.getConnectionInfo(); 42 | if (info != null) return info.getMacAddress(); 43 | } 44 | } catch (Exception e) { 45 | e.printStackTrace(); 46 | } 47 | return "02:00:00:00:00:00"; 48 | } 49 | 50 | /** 51 | * 获取 IMEI 码 52 | *

需添加权限 53 | * {@code }

54 | * 55 | * @return IMEI 码 56 | */ 57 | @SuppressLint({"HardwareIds", "MissingPermission"}) 58 | public static String getIMEI(Context context) { 59 | try { 60 | TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); 61 | return tm != null ? tm.getDeviceId() : null; 62 | } catch (Exception e) { 63 | e.printStackTrace(); 64 | } 65 | return null; 66 | } 67 | 68 | /** 69 | * 获取设备厂商 70 | *

如 Xiaomi

71 | * 72 | * @return 设备厂商 73 | */ 74 | 75 | public static String getManufacturer() { 76 | return Build.MANUFACTURER; 77 | } 78 | 79 | /** 80 | * 获取设备型号 81 | *

如 MI2SC

82 | * 83 | * @return 设备型号 84 | */ 85 | public static String getModel() { 86 | String model = Build.MODEL; 87 | if (model != null) { 88 | model = model.trim().replaceAll("\\s*", ""); 89 | } else { 90 | model = ""; 91 | } 92 | return model; 93 | } 94 | 95 | } 96 | -------------------------------------------------------------------------------- /libUtils/src/main/java/com/lzy/utils/system/ScreenUtil.java: -------------------------------------------------------------------------------- 1 | package com.lzy.utils.system; 2 | 3 | import android.content.Context; 4 | import android.graphics.Point; 5 | import android.view.WindowManager; 6 | 7 | /** 8 | * 手机屏幕尺寸工具类 9 | * 10 | * @author: cyli8 11 | * @date: 2018/2/11 17:05 12 | */ 13 | 14 | public class ScreenUtil { 15 | /** 16 | * 获取屏幕的宽度(单位:px) 17 | * 18 | * @return 屏幕宽 19 | */ 20 | public static int getScreenWidth(Context context) { 21 | WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); 22 | if (wm == null) { 23 | return context.getResources().getDisplayMetrics().widthPixels; 24 | } 25 | Point point = new Point(); 26 | wm.getDefaultDisplay().getRealSize(point); 27 | return point.x; 28 | } 29 | 30 | /** 31 | * 获取屏幕的高度(单位:px) 32 | * 33 | * @return 屏幕高 34 | */ 35 | public static int getScreenHeight(Context context) { 36 | WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); 37 | if (wm == null) { 38 | return context.getResources().getDisplayMetrics().heightPixels; 39 | } 40 | Point point = new Point(); 41 | wm.getDefaultDisplay().getRealSize(point); 42 | return point.y; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /libUtils/src/main/java/com/lzy/utils/url/UrlEncode.java: -------------------------------------------------------------------------------- 1 | package com.lzy.utils.url; 2 | 3 | import java.io.UnsupportedEncodingException; 4 | import java.net.URLDecoder; 5 | import java.net.URLEncoder; 6 | import java.util.regex.Matcher; 7 | import java.util.regex.Pattern; 8 | 9 | /** 10 | * url编码工具类 11 | * 12 | * @author: cyli8 13 | * @date: 2018/2/23 09:22 14 | */ 15 | 16 | public class UrlEncode { 17 | public static String decode(final String url) { 18 | try { 19 | return URLDecoder.decode(url, "utf-8"); 20 | } catch (final UnsupportedEncodingException e) { 21 | e.printStackTrace(); 22 | } 23 | return null; 24 | } 25 | 26 | public static String encode(String url, final String code) { 27 | if (null == url) { 28 | return url; 29 | } 30 | final Matcher matcher = Pattern.compile("[\\u4e00-\\u9fa5]").matcher(url); 31 | while (matcher.find()) { 32 | String tmp = matcher.group(); 33 | try { 34 | url = url.replaceAll(tmp, URLEncoder.encode(tmp, code)); 35 | } catch (UnsupportedEncodingException e) { 36 | e.printStackTrace(); 37 | } 38 | } 39 | return url; 40 | } 41 | 42 | public static String encodeGBK(final String url) { 43 | return encode(url, "gbk"); 44 | } 45 | 46 | public static String encodeUTF8(final String url) { 47 | return encode(url, "utf-8"); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /libUtils/src/main/java/com/lzy/utils/url/UrlHelper.java: -------------------------------------------------------------------------------- 1 | package com.lzy.utils.url; 2 | 3 | /** 4 | * url帮助类 5 | * 6 | * @author: cyli8 7 | * @date: 2018/2/23 09:18 8 | */ 9 | 10 | public class UrlHelper { 11 | public static final String getFileNameFromUrl(final String url) { 12 | if (null == url || "".equalsIgnoreCase(url.trim())) { 13 | return url; 14 | } 15 | String flag = "/"; 16 | String tmp = url.toLowerCase(); 17 | int last = tmp.lastIndexOf(flag); 18 | if (last == url.length() - 1) { 19 | return null; 20 | } 21 | tmp = tmp.substring(last + 1); 22 | if (tmp.contains("?")) {//新上传到oss上的文件url附加了部分参数 23 | int index = tmp.indexOf("?"); 24 | if (index > 0) { 25 | tmp = tmp.substring(0, index); 26 | } 27 | } 28 | String name = UrlEncode.decode(tmp); 29 | int length = name.length(); 30 | if (name != null && length > 7) { 31 | name = name.substring(length - 7); 32 | } 33 | return name; 34 | } 35 | 36 | public static final boolean isUrlValid(String url) { 37 | if (null == url || "".equals(url.trim())) { 38 | return false; 39 | } 40 | url = url.trim(); 41 | return url.startsWith("http://") || url.startsWith("https://"); 42 | } 43 | 44 | public static boolean isAssetsUrl(String url) { 45 | if (null == url || "".equals(url.trim())) { 46 | return false; 47 | } 48 | url = url.trim(); 49 | return url.startsWith("asset://"); 50 | } 51 | 52 | public static boolean isHttpUrl(String url, boolean https) { 53 | if (null == url) { 54 | return false; 55 | } 56 | url = url.trim().toLowerCase(); 57 | if (!https) { 58 | return url.startsWith("http://"); 59 | } 60 | return url.startsWith("http://") || url.startsWith("https://"); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /libUtils/src/main/res/values/ids.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /libUtils/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | libutils 3 | 4 | -------------------------------------------------------------------------------- /libView/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /libView/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | 3 | android { 4 | compileSdkVersion rootProject.ext.compileSdkVersion 5 | 6 | defaultConfig { 7 | minSdkVersion rootProject.ext.minSdkVersion 8 | targetSdkVersion rootProject.ext.targetSdkVersion 9 | versionCode 1 10 | versionName "1.0" 11 | 12 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 13 | 14 | } 15 | 16 | buildTypes { 17 | release { 18 | minifyEnabled true 19 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 20 | } 21 | } 22 | 23 | resourcePrefix "lib_view_" 24 | } 25 | 26 | dependencies { 27 | implementation fileTree(include: ['*.jar'], dir: 'libs') 28 | implementation project(':libBaseFun') 29 | api 'androidx.appcompat:appcompat:' + rootProject.ext.androidXVersion 30 | api 'androidx.constraintlayout:constraintlayout:1.1.3' 31 | api 'pub.devrel:easypermissions:3.0.0' 32 | api 'com.google.android.material:material:1.0.0' 33 | api 'com.yanzhenjie.recyclerview:x:1.3.2' 34 | } 35 | -------------------------------------------------------------------------------- /libView/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | -------------------------------------------------------------------------------- /libView/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 7 | 8 | 12 | 13 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /libView/src/main/java/com/lzy/libview/activity/BaseActivity.java: -------------------------------------------------------------------------------- 1 | package com.lzy.libview.activity; 2 | 3 | import android.content.Intent; 4 | 5 | import androidx.annotation.NonNull; 6 | import androidx.appcompat.app.AppCompatActivity; 7 | 8 | import com.lzy.libview.R; 9 | import com.lzy.libview.permission.OnPermissionListener; 10 | 11 | import java.util.List; 12 | 13 | import pub.devrel.easypermissions.AppSettingsDialog; 14 | import pub.devrel.easypermissions.EasyPermissions; 15 | import pub.devrel.easypermissions.PermissionRequest; 16 | 17 | /** 18 | * 基础activity,所有业务Activity均继承于它 19 | * 加入运行时权限申请的接口 2018/3/2 10:28 20 | * 21 | * @author: cyli8 22 | * @date: 2018/2/28 10:44 23 | */ 24 | 25 | public class BaseActivity extends AppCompatActivity implements EasyPermissions.PermissionCallbacks { 26 | 27 | //运行时权限部分 28 | private OnPermissionListener mPermissionListener; 29 | private int mRequestPermCode; 30 | 31 | /** 32 | * 检查并且申请运行时权限 33 | * 34 | * @param rationaleStr 用户拒绝后的声明需要权限的提示语,为空则用户拒绝后不再进行后续权限申请 35 | * @param requestCode 请求code 36 | * @param listener 回调监听 37 | * @param permissions 权限组 38 | */ 39 | public void checkAndRequestPermissions(String rationaleStr, int requestCode, 40 | OnPermissionListener listener, String... permissions) { 41 | checkAndRequestPermissions(rationaleStr, R.string.lib_view_ok, 42 | R.string.lib_view_cancel, requestCode, listener, permissions); 43 | } 44 | 45 | public void checkAndRequestPermissions(String rationaleStr, int positiveId, 46 | int negativeId, int requestCode, 47 | OnPermissionListener listener, String... permissions) { 48 | mRequestPermCode = requestCode; 49 | mPermissionListener = listener; 50 | PermissionRequest request = new PermissionRequest.Builder(this, requestCode, permissions) 51 | .setRationale(rationaleStr) 52 | .setPositiveButtonText(positiveId) 53 | .setNegativeButtonText(negativeId) 54 | .build(); 55 | EasyPermissions.requestPermissions(request); 56 | } 57 | 58 | @Override 59 | public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, 60 | @NonNull int[] grantResults) { 61 | super.onRequestPermissionsResult(requestCode, permissions, grantResults); 62 | EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, 63 | this); 64 | } 65 | 66 | @Override 67 | public void onPermissionsGranted(int requestCode, @NonNull List perms) { 68 | if (mPermissionListener != null) { 69 | mPermissionListener.onPermGranted(requestCode, perms); 70 | } 71 | } 72 | 73 | @Override 74 | public void onPermissionsDenied(int requestCode, @NonNull List perms) { 75 | if (mPermissionListener != null) { 76 | mPermissionListener.onPermDenied(requestCode, perms); 77 | } 78 | } 79 | 80 | public boolean gotoSettingActivity(List perms, String rationale) { 81 | return gotoSettingActivity(perms, rationale, getString(R.string.lib_view_ok), 82 | getString(R.string.lib_view_cancel)); 83 | } 84 | 85 | private boolean gotoSettingActivity(List perms, String rationale, String positiveStr, String negativeStr) { 86 | if (EasyPermissions.somePermissionPermanentlyDenied(this, perms)) { 87 | //用户选中了不再提示 88 | new AppSettingsDialog.Builder(this) 89 | .setTitle(R.string.lib_view_title_settings_dialog) 90 | .setRationale(rationale) 91 | .setPositiveButton(positiveStr) 92 | .setNegativeButton(negativeStr) 93 | .build() 94 | .show(); 95 | return true; 96 | } 97 | return false; 98 | } 99 | 100 | @Override 101 | protected void onActivityResult(int requestCode, int resultCode, Intent data) { 102 | super.onActivityResult(requestCode, resultCode, data); 103 | //运行时权限的结果回调 104 | if (requestCode == AppSettingsDialog.DEFAULT_SETTINGS_REQ_CODE) { 105 | if (mPermissionListener != null) { 106 | mPermissionListener.onPermSystemSettingResult(mRequestPermCode); 107 | } 108 | } 109 | } 110 | 111 | } 112 | -------------------------------------------------------------------------------- /libView/src/main/java/com/lzy/libview/activity/BaseFragmentActivity.java: -------------------------------------------------------------------------------- 1 | package com.lzy.libview.activity; 2 | 3 | import android.content.Intent; 4 | import android.os.Bundle; 5 | 6 | import androidx.fragment.app.FragmentTransaction; 7 | 8 | import com.lzy.libview.R; 9 | import com.lzy.libview.fragment.BaseFragment; 10 | 11 | /** 12 | * 用于承载和显示Fragment内容的类,实现相关通用逻辑 13 | * 14 | * @author: cyli8 15 | * @date: 2018/2/28 11:00 16 | */ 17 | 18 | public class BaseFragmentActivity extends BaseActivity { 19 | 20 | public static final String KEY_FRAGMENT_CLASS_NAME = "fragment_class_name"; 21 | 22 | private BaseFragment mFragment; 23 | 24 | @Override 25 | protected void onCreate(Bundle savedInstanceState) { 26 | super.onCreate(savedInstanceState); 27 | setContentView(getLayoutID()); 28 | Intent intent = getIntent(); 29 | initArgument(intent); 30 | mFragment = getFragment(intent); 31 | if (null == mFragment) { 32 | finish(); 33 | return; 34 | } 35 | // 管理器 36 | FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction(); 37 | fragmentTransaction.add(R.id.container, mFragment, "fragment"); 38 | fragmentTransaction.commitAllowingStateLoss(); 39 | } 40 | 41 | protected void initArgument(Intent intent) { 42 | 43 | } 44 | 45 | protected int getLayoutID() { 46 | return R.layout.lib_view_activity_base; 47 | } 48 | 49 | protected BaseFragment getFragment(Intent intent) { 50 | String clsName = intent.getStringExtra(KEY_FRAGMENT_CLASS_NAME); 51 | if (null != clsName) { 52 | try { 53 | BaseFragment fragment = (BaseFragment) Class.forName(clsName).newInstance(); 54 | fragment.setArguments(intent.getExtras()); 55 | return fragment; 56 | } catch (IllegalAccessException | InstantiationException | ClassNotFoundException e) { 57 | e.printStackTrace(); 58 | } 59 | } 60 | return null; 61 | } 62 | 63 | } 64 | -------------------------------------------------------------------------------- /libView/src/main/java/com/lzy/libview/activity/BaseTitleFragmentActivity.java: -------------------------------------------------------------------------------- 1 | package com.lzy.libview.activity; 2 | 3 | import android.content.Intent; 4 | import android.os.Bundle; 5 | import android.view.View; 6 | import android.widget.TextView; 7 | 8 | import androidx.appcompat.app.ActionBar; 9 | import androidx.appcompat.widget.Toolbar; 10 | 11 | import com.lzy.libview.R; 12 | 13 | /** 14 | * @author: cyli8 15 | * @date: 2018/2/28 11:40 16 | */ 17 | 18 | public class BaseTitleFragmentActivity extends BaseFragmentActivity { 19 | public static final String KEY_ACTIVITY_TITLE = "key_activity_title"; 20 | private Toolbar mToolbar; 21 | private String mTitle; 22 | private TextView mTitleTv; 23 | 24 | @Override 25 | protected void onCreate(Bundle savedInstanceState) { 26 | super.onCreate(savedInstanceState); 27 | mToolbar = findViewById(R.id.toolbar); 28 | setSupportActionBar(mToolbar); 29 | ActionBar actionBar = getSupportActionBar(); 30 | if (actionBar != null) { 31 | actionBar.setDisplayShowTitleEnabled(false); 32 | } 33 | mToolbar.setNavigationIcon(R.mipmap.lib_view_back); 34 | mToolbar.setNavigationOnClickListener(new View.OnClickListener() { 35 | @Override 36 | public void onClick(View v) { 37 | BaseTitleFragmentActivity.this.onBackPressed(); 38 | } 39 | }); 40 | mTitleTv = findViewById(R.id.title_tv); 41 | setTitle(mTitle); 42 | } 43 | 44 | @Override 45 | protected int getLayoutID() { 46 | return R.layout.lib_view_activity_base_title; 47 | } 48 | 49 | @Override 50 | protected void initArgument(Intent intent) { 51 | mTitle = intent.getStringExtra(KEY_ACTIVITY_TITLE); 52 | } 53 | 54 | public void setTitle(String title) { 55 | mTitleTv.setText(title); 56 | } 57 | 58 | } 59 | -------------------------------------------------------------------------------- /libView/src/main/java/com/lzy/libview/activity/IClickRightButtonAble.java: -------------------------------------------------------------------------------- 1 | package com.lzy.libview.activity; 2 | 3 | /** 4 | * 用于Fragment集成实现,当需要右键点击事件的时候,框架中的Activity会把导航栏右键的点击事件分发给Fragment去实现逻辑 5 | * 6 | * @author: cyli8 7 | * @date: 2018/2/28 11:55 8 | */ 9 | 10 | public interface IClickRightButtonAble { 11 | void onClickRightTv(); 12 | 13 | void onClickRightBtn(); 14 | 15 | CharSequence getRightButtonTv(); 16 | 17 | int getRightButtonImgId(); 18 | } 19 | -------------------------------------------------------------------------------- /libView/src/main/java/com/lzy/libview/activity/IListBacktop.java: -------------------------------------------------------------------------------- 1 | package com.lzy.libview.activity; 2 | 3 | /** 4 | * 点击页面标题滚动到顶部接口 5 | * 6 | * @author: cyli8 7 | * @date: 2018/2/28 11:59 8 | */ 9 | 10 | public interface IListBacktop { 11 | void scrollToTop(); 12 | } 13 | -------------------------------------------------------------------------------- /libView/src/main/java/com/lzy/libview/activity/IOnKeyDownEvent.java: -------------------------------------------------------------------------------- 1 | package com.lzy.libview.activity; 2 | 3 | import android.view.KeyEvent; 4 | 5 | /** 6 | * @author: cyli8 7 | * @date: 2018/2/28 11:38 8 | */ 9 | 10 | public interface IOnKeyDownEvent { 11 | boolean onKeyDownEvent(int keyCode, KeyEvent event); 12 | } 13 | -------------------------------------------------------------------------------- /libView/src/main/java/com/lzy/libview/custom/ResizeLayout.java: -------------------------------------------------------------------------------- 1 | package com.lzy.libview.custom; 2 | 3 | import android.content.Context; 4 | import android.graphics.Point; 5 | import android.util.AttributeSet; 6 | import android.view.WindowManager; 7 | import android.widget.RelativeLayout; 8 | 9 | /** 10 | * 可监听布局的大小变化以及软键盘的弹出或隐藏 11 | * 12 | * @author: cyli8 13 | * @date: 2018/2/28 17:17 14 | */ 15 | 16 | public class ResizeLayout extends RelativeLayout { 17 | public interface OnSizeChangedListener { 18 | void onSizeChanged(int l, int t, int r, int b, int h, 19 | boolean showing); 20 | } 21 | 22 | private OnSizeChangedListener mSizeChangedListener; 23 | 24 | private boolean mShowInput; 25 | private int mScreenHeight; 26 | 27 | public ResizeLayout(Context context) { 28 | super(context); 29 | mScreenHeight = getScreenHeight(context); 30 | } 31 | 32 | public ResizeLayout(Context context, AttributeSet attrs) { 33 | super(context, attrs); 34 | mScreenHeight = getScreenHeight(context); 35 | } 36 | 37 | public ResizeLayout(Context context, AttributeSet attrs, int defStyle) { 38 | super(context, attrs, defStyle); 39 | mScreenHeight = getScreenHeight(context); 40 | } 41 | 42 | public void setOnSizeChangedListener(OnSizeChangedListener l) { 43 | mSizeChangedListener = l; 44 | } 45 | 46 | @Override 47 | protected void onSizeChanged(int w, final int h, int oldw, final int oldh) { 48 | super.onSizeChanged(w, h, oldw, oldh); 49 | if (oldh > h && oldh < mScreenHeight && (oldh - h) > (mScreenHeight / 3)) { //这里阀值设为屏幕高的1/3 50 | // 软键盘弹出 51 | mShowInput = true; 52 | } else if ((h - oldh) > (mScreenHeight / 3)) { 53 | // 软键盘收起 54 | mShowInput = false; 55 | } 56 | } 57 | 58 | private int mTop = 0; 59 | private int mBot = 0; 60 | 61 | @Override 62 | protected void onLayout(boolean changed, int l, int t, int r, int b) { 63 | if (mTop == 0 && mBot == 0) { 64 | mTop = t; 65 | mBot = b; 66 | } else { 67 | int h = mBot - mTop; 68 | mTop = t; 69 | mBot = b; 70 | if (null != mSizeChangedListener && changed) { 71 | mSizeChangedListener.onSizeChanged(l, t, r, b, h, mShowInput); 72 | } 73 | } 74 | super.onLayout(changed, l, t, r, b); 75 | } 76 | 77 | @Override 78 | protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 79 | super.onMeasure(widthMeasureSpec, heightMeasureSpec); 80 | } 81 | 82 | /** 83 | * 获取屏幕的高度(单位:px) 84 | * 85 | * @return 屏幕高 86 | */ 87 | public static int getScreenHeight(Context context) { 88 | WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); 89 | if (wm == null) { 90 | return context.getResources().getDisplayMetrics().heightPixels; 91 | } 92 | Point point = new Point(); 93 | wm.getDefaultDisplay().getRealSize(point); 94 | return point.y; 95 | } 96 | 97 | } 98 | -------------------------------------------------------------------------------- /libView/src/main/java/com/lzy/libview/dialog/BaseDialogFragment.java: -------------------------------------------------------------------------------- 1 | package com.lzy.libview.dialog; 2 | 3 | import android.os.Bundle; 4 | import android.util.DisplayMetrics; 5 | import android.view.Gravity; 6 | import android.view.LayoutInflater; 7 | import android.view.View; 8 | import android.view.ViewGroup; 9 | import android.view.Window; 10 | import android.view.WindowManager; 11 | 12 | import androidx.annotation.NonNull; 13 | import androidx.annotation.Nullable; 14 | import androidx.fragment.app.DialogFragment; 15 | import androidx.fragment.app.FragmentManager; 16 | 17 | import com.lzy.libview.R; 18 | 19 | 20 | /** 21 | * @author: cyli8 22 | * @date: 2019-10-08 17:14 23 | */ 24 | public abstract class BaseDialogFragment extends DialogFragment { 25 | 26 | @Override 27 | public void onCreate(@Nullable Bundle savedInstanceState) { 28 | super.onCreate(savedInstanceState); 29 | setStyle(DialogFragment.STYLE_NO_FRAME, R.style.lib_view_theme_basedialog); 30 | } 31 | 32 | @Nullable 33 | @Override 34 | public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { 35 | View view = initView(inflater); 36 | requestOrLoadData(); 37 | return view; 38 | } 39 | 40 | @Override 41 | public void onStart() { 42 | super.onStart(); 43 | initWindow(); 44 | } 45 | 46 | protected void initWindow() { 47 | if (getDialog() != null) { 48 | Window window = getDialog().getWindow(); 49 | if (window != null) { 50 | DisplayMetrics metrics = getResources().getDisplayMetrics(); 51 | int width = (int) (metrics.widthPixels * 0.8); 52 | window.setLayout(width, WindowManager.LayoutParams.WRAP_CONTENT); 53 | window.setGravity(Gravity.CENTER); 54 | } 55 | } 56 | } 57 | 58 | protected abstract View initView(LayoutInflater inflater); 59 | 60 | protected void requestOrLoadData() { 61 | 62 | } 63 | 64 | @Override 65 | public void show(FragmentManager manager, String tag) { 66 | try { 67 | if (manager != null) { 68 | //防止连续点击add多个fragment 69 | manager.beginTransaction().remove(this).commit(); 70 | super.show(manager, tag); 71 | } 72 | } catch (Exception e) { 73 | e.printStackTrace(); 74 | } 75 | } 76 | 77 | } 78 | -------------------------------------------------------------------------------- /libView/src/main/java/com/lzy/libview/dialog/CustomAskDialog.java: -------------------------------------------------------------------------------- 1 | package com.lzy.libview.dialog; 2 | 3 | import android.text.TextUtils; 4 | import android.view.LayoutInflater; 5 | import android.view.View; 6 | import android.widget.TextView; 7 | 8 | import com.lzy.libview.R; 9 | 10 | /** 11 | * 对话框 12 | * 13 | * @author: cyli8 14 | * @date: 2018/2/28 10:20 15 | */ 16 | 17 | public class CustomAskDialog extends BaseDialogFragment implements View.OnClickListener { 18 | 19 | public interface OnAskDlgListener { 20 | void onClickOk(); 21 | 22 | void onClickCancel(); 23 | } 24 | 25 | private TextView mOkTv; 26 | private TextView mCancelTv; 27 | private OnAskDlgListener mDlgListener; 28 | 29 | private String title, content; 30 | 31 | public CustomAskDialog(String title, String content) { 32 | this.title = title; 33 | this.content = content; 34 | } 35 | 36 | public void setListener(OnAskDlgListener l) { 37 | mDlgListener = l; 38 | } 39 | 40 | public void setCancelViewGone() { 41 | mCancelTv.setVisibility(View.GONE); 42 | } 43 | 44 | @Override 45 | protected View initView(LayoutInflater inflater) { 46 | View view = inflater.inflate((R.layout.lib_view_ask_dlg), null); 47 | TextView titleTv = view.findViewById(R.id.title); 48 | if (TextUtils.isEmpty(title)) { 49 | titleTv.setVisibility(View.GONE); 50 | } else { 51 | titleTv.setText(title); 52 | } 53 | TextView contentTv = view.findViewById(R.id.content); 54 | if (TextUtils.isEmpty(content)) { 55 | contentTv.setVisibility(View.GONE); 56 | } else { 57 | contentTv.setText(content); 58 | } 59 | mOkTv = view.findViewById(R.id.dlg_ok); 60 | mOkTv.setOnClickListener(this); 61 | mCancelTv = view.findViewById(R.id.dlg_cancel); 62 | mCancelTv.setOnClickListener(this); 63 | return view; 64 | } 65 | 66 | public void setOkStr(String okStr) { 67 | if (!TextUtils.isEmpty(okStr)) { 68 | mOkTv.setText(okStr); 69 | } 70 | } 71 | 72 | public void setCancelStr(String cancelStr) { 73 | if (!TextUtils.isEmpty(cancelStr)) { 74 | mCancelTv.setText(cancelStr); 75 | } 76 | } 77 | 78 | @Override 79 | public void onClick(View v) { 80 | int id = v.getId(); 81 | if (id == R.id.dlg_cancel) { 82 | dismiss(); 83 | if (null != mDlgListener) { 84 | mDlgListener.onClickCancel(); 85 | } 86 | } else if (id == R.id.dlg_ok) { 87 | dismiss(); 88 | if (null != mDlgListener) { 89 | mDlgListener.onClickOk(); 90 | } 91 | } 92 | } 93 | 94 | } 95 | -------------------------------------------------------------------------------- /libView/src/main/java/com/lzy/libview/dialog/CustomWaitingDialog.java: -------------------------------------------------------------------------------- 1 | package com.lzy.libview.dialog; 2 | 3 | import android.app.Dialog; 4 | import android.content.Context; 5 | import android.graphics.Color; 6 | import android.graphics.drawable.ColorDrawable; 7 | import android.os.Bundle; 8 | import android.text.TextUtils; 9 | import android.view.View; 10 | import android.view.Window; 11 | import android.view.WindowManager; 12 | import android.widget.TextView; 13 | 14 | import androidx.annotation.NonNull; 15 | 16 | import com.lzy.libview.R; 17 | 18 | /** 19 | * 等待框 20 | * 21 | * @author: cyli8 22 | * @date: 2018/2/28 10:47 23 | */ 24 | 25 | public class CustomWaitingDialog extends Dialog { 26 | 27 | private String mTips; 28 | private TextView mTipsTv; 29 | 30 | public CustomWaitingDialog(@NonNull Context context) { 31 | super(context); 32 | setCanceledOnTouchOutside(false); 33 | } 34 | 35 | public CustomWaitingDialog(Context context, String tips) { 36 | super(context); 37 | setCanceledOnTouchOutside(false); 38 | mTips = tips; 39 | } 40 | 41 | @Override 42 | protected void onCreate(Bundle savedInstanceState) { 43 | super.onCreate(savedInstanceState); 44 | requestWindowFeature(Window.FEATURE_NO_TITLE); 45 | setContentView(R.layout.lib_view_progress_dialog_layout); 46 | findViewById(R.id.root).setBackgroundColor(Color.TRANSPARENT); 47 | if (TextUtils.isEmpty(mTips)) { 48 | findViewById(R.id.tips_tv).setVisibility(View.GONE); 49 | } else { 50 | mTipsTv = findViewById(R.id.tips_tv); 51 | mTipsTv.setVisibility(View.VISIBLE); 52 | mTipsTv.setText(mTips); 53 | } 54 | Window window = getWindow(); 55 | if (window != null) { 56 | window.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT)); 57 | WindowManager.LayoutParams lp = window.getAttributes(); 58 | lp.width = WindowManager.LayoutParams.MATCH_PARENT; 59 | lp.height = WindowManager.LayoutParams.MATCH_PARENT; 60 | window.setAttributes(lp); 61 | } 62 | } 63 | 64 | public void updateTips(String tips) { 65 | mTipsTv.setText(tips); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /libView/src/main/java/com/lzy/libview/fragment/BaseFragment.java: -------------------------------------------------------------------------------- 1 | package com.lzy.libview.fragment; 2 | 3 | import android.content.DialogInterface; 4 | import android.os.Bundle; 5 | import android.widget.Toast; 6 | 7 | import androidx.annotation.Nullable; 8 | import androidx.fragment.app.Fragment; 9 | 10 | import com.lzy.libview.dialog.CustomWaitingDialog; 11 | import com.lzy.libview.mvp.AbstractBasePresenter; 12 | import com.lzy.libview.mvp.IBaseView; 13 | 14 | /** 15 | * Fragment基类,所有业务Fragment均继承于此,统一定义公共逻辑 16 | * 为了和{@link com.lzy.libview.activity.BaseTitleFragmentActivity} 配合使用,增加的Title,Activity间通信等逻辑相关函数 17 | * 18 | * @author: cyli8 19 | * @date: 2018/2/28 11:03 20 | */ 21 | 22 | public class BaseFragment extends Fragment implements IBaseView { 23 | 24 | protected T mPresenter; 25 | 26 | @Override 27 | public void onCreate(@Nullable Bundle savedInstanceState) { 28 | super.onCreate(savedInstanceState); 29 | Bundle bundle = getArguments(); 30 | if (bundle != null) { 31 | initArgument(bundle); 32 | } 33 | mPresenter = createPresenter(); 34 | } 35 | 36 | protected void initArgument(Bundle bundle) { 37 | 38 | } 39 | 40 | protected T createPresenter() { 41 | return null; 42 | } 43 | 44 | private CustomWaitingDialog mWaitingDialog; 45 | 46 | @Override 47 | public void showWaitingDialog(String tips, boolean cancel, DialogInterface.OnCancelListener listener) { 48 | if (getActivity() == null) { 49 | return; 50 | } 51 | if (null == mWaitingDialog) { 52 | mWaitingDialog = new CustomWaitingDialog(getActivity(), tips); 53 | } 54 | if (listener != null) { 55 | mWaitingDialog.setOnCancelListener(listener); 56 | } 57 | mWaitingDialog.setCancelable(cancel); 58 | mWaitingDialog.show(); 59 | } 60 | 61 | @Override 62 | public void dismissWaitingDialog() { 63 | if (null != mWaitingDialog && mWaitingDialog.isShowing()) { 64 | mWaitingDialog.dismiss(); 65 | mWaitingDialog = null; 66 | } 67 | } 68 | 69 | @Override 70 | public void toast(CharSequence text) { 71 | if (isViewAttached()) { 72 | Toast.makeText(getContext(), text, Toast.LENGTH_SHORT).show(); 73 | } 74 | } 75 | 76 | @Override 77 | public void toast(int resId) { 78 | if (isViewAttached()) { 79 | Toast.makeText(getContext(), resId, Toast.LENGTH_SHORT).show(); 80 | } 81 | } 82 | 83 | @Override 84 | public boolean isViewAttached() { 85 | return getHost() != null && getContext() != null && isAdded(); 86 | } 87 | 88 | @Override 89 | public void onDestroy() { 90 | super.onDestroy(); 91 | if (mPresenter != null) { 92 | mPresenter.destroy(); 93 | mPresenter = null; 94 | } 95 | } 96 | 97 | } 98 | -------------------------------------------------------------------------------- /libView/src/main/java/com/lzy/libview/mvp/AbstractBasePresenter.java: -------------------------------------------------------------------------------- 1 | package com.lzy.libview.mvp; 2 | 3 | import android.content.Context; 4 | 5 | import io.reactivex.disposables.CompositeDisposable; 6 | import io.reactivex.disposables.Disposable; 7 | 8 | /** 9 | * @author: cyli8 10 | * @date: 2019-12-12 13:56 11 | */ 12 | public abstract class AbstractBasePresenter implements IBasePresenter { 13 | 14 | protected Context mContext; 15 | protected T mView; 16 | 17 | private CompositeDisposable mCompositeDisposable; 18 | 19 | public void addDisposable(Disposable disposable) { 20 | if (mCompositeDisposable == null) { 21 | mCompositeDisposable = new CompositeDisposable(); 22 | mCompositeDisposable.add(disposable); 23 | } 24 | } 25 | 26 | @Override 27 | public void destroy() { 28 | cancelRequest(); 29 | if (mCompositeDisposable != null) { 30 | mCompositeDisposable.clear(); 31 | } 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /libView/src/main/java/com/lzy/libview/mvp/IBasePresenter.java: -------------------------------------------------------------------------------- 1 | package com.lzy.libview.mvp; 2 | 3 | /** 4 | * 基础页面presenter接口 5 | * 6 | * @author: cyli8 7 | * @date: 2018/2/28 11:14 8 | */ 9 | 10 | public interface IBasePresenter { 11 | /** 12 | * 取消页面请求 13 | */ 14 | void cancelRequest(); 15 | 16 | /** 17 | * 页面销毁 18 | */ 19 | void destroy(); 20 | } 21 | -------------------------------------------------------------------------------- /libView/src/main/java/com/lzy/libview/mvp/IBaseView.java: -------------------------------------------------------------------------------- 1 | package com.lzy.libview.mvp; 2 | 3 | import android.content.DialogInterface; 4 | 5 | /** 6 | * 基础fragment页面接口 7 | * 8 | * @author: cyli8 9 | * @date: 2018/2/28 11:25 10 | */ 11 | 12 | public interface IBaseView { 13 | /** 14 | * 页面是否已依附到activity 15 | * 16 | * @return true, 已加载 17 | */ 18 | boolean isViewAttached(); 19 | 20 | /** 21 | * 等待框 22 | * 23 | * @param tips 提示语 24 | */ 25 | void showWaitingDialog(String tips, boolean cancel, DialogInterface.OnCancelListener listener); 26 | 27 | /** 28 | * 消失等待对话框 29 | */ 30 | void dismissWaitingDialog(); 31 | 32 | /** 33 | * toast 34 | * 35 | * @param text 文本 36 | */ 37 | void toast(CharSequence text); 38 | 39 | /** 40 | * toast 41 | * 42 | * @param resId 资源id 43 | */ 44 | void toast(int resId); 45 | } 46 | -------------------------------------------------------------------------------- /libView/src/main/java/com/lzy/libview/permission/OnPermissionListener.java: -------------------------------------------------------------------------------- 1 | package com.lzy.libview.permission; 2 | 3 | import java.util.List; 4 | 5 | /** 6 | * @author: cyli8 7 | * @date: 2019-12-11 17:38 8 | */ 9 | public interface OnPermissionListener { 10 | void onPermGranted(int requestCode, List perms); 11 | 12 | void onPermDenied(int requestCode, List perms); 13 | 14 | void onPermSystemSettingResult(int requestCode); 15 | } 16 | -------------------------------------------------------------------------------- /libView/src/main/res/anim/lib_view_anim_none.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | -------------------------------------------------------------------------------- /libView/src/main/res/drawable/lib_view_btn_empty_tip.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /libView/src/main/res/drawable/lib_view_btn_empty_tip_nor.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /libView/src/main/res/drawable/lib_view_btn_empty_tip_sel.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /libView/src/main/res/drawable/lib_view_dlg_ask_bg.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /libView/src/main/res/drawable/lib_view_dlg_progress_bar.xml: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /libView/src/main/res/drawable/lib_view_ripple_bg.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /libView/src/main/res/drawable/lib_view_webview_progressbar_style.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /libView/src/main/res/layout/lib_view_activity_base.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 15 | 16 | -------------------------------------------------------------------------------- /libView/src/main/res/layout/lib_view_activity_base_title.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 17 | 18 | 28 | 29 | 30 | 31 | 39 | 40 | -------------------------------------------------------------------------------- /libView/src/main/res/layout/lib_view_ask_dlg.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 15 | 16 | 25 | 26 | 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /libView/src/main/res/layout/lib_view_cancel_ok_btns.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | 22 | 23 | 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /libView/src/main/res/layout/lib_view_layout_empty_tips.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 21 | 22 | 35 | 36 | -------------------------------------------------------------------------------- /libView/src/main/res/layout/lib_view_progress_dialog_layout.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 11 | 12 | 17 | 18 | 25 | 26 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /libView/src/main/res/mipmap-xxhdpi/ic_menu_more_overflow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lzyang187/FastDevelop/86dc57026a8b4e9b193891edbecb6ee594de157a/libView/src/main/res/mipmap-xxhdpi/ic_menu_more_overflow.png -------------------------------------------------------------------------------- /libView/src/main/res/mipmap-xxhdpi/lib_view_back.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lzyang187/FastDevelop/86dc57026a8b4e9b193891edbecb6ee594de157a/libView/src/main/res/mipmap-xxhdpi/lib_view_back.png -------------------------------------------------------------------------------- /libView/src/main/res/mipmap-xxhdpi/lib_view_dlg_progress.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lzyang187/FastDevelop/86dc57026a8b4e9b193891edbecb6ee594de157a/libView/src/main/res/mipmap-xxhdpi/lib_view_dlg_progress.png -------------------------------------------------------------------------------- /libView/src/main/res/mipmap-xxhdpi/lib_view_icon_network_error.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lzyang187/FastDevelop/86dc57026a8b4e9b193891edbecb6ee594de157a/libView/src/main/res/mipmap-xxhdpi/lib_view_icon_network_error.png -------------------------------------------------------------------------------- /libView/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #fa436f 4 | #e0fa436f 5 | #00000000 6 | #f4f9ff 7 | #f4f9ff 8 | #e0e0e0 9 | 10 | #e0e0e0 11 | #ffffff 12 | 13 | #ffffff 14 | #00000000 15 | 16 | #ffffff 17 | #00000000 18 | #88ffffff 19 | #88000000 20 | #40000000 21 | #000000 22 | #e0e0ee 23 | #e0e0ee 24 | 25 | 26 | -------------------------------------------------------------------------------- /libView/src/main/res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 48dp 5 | 48dp 6 | 18sp 7 | 8 | 70dp 9 | 10 | 11 | -------------------------------------------------------------------------------- /libView/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | libView 3 | 4 | 请求权限 5 | 授予权限功能才能正常使用,点击跳转到系统设置页面授予权限。 6 | 确定 7 | 取消 8 | 开启权限 9 | 知道了 10 | 11 | 当前网络不可用\n请检查后点击屏幕重试 12 | 13 | 14 | -------------------------------------------------------------------------------- /libView/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 15 | 16 | 26 | 27 | 28 | 36 | 37 | 42 | 43 | 51 | 52 | 57 | 58 | 59 | 62 | 63 | 67 | 68 | 69 | 73 | 74 | 79 | 80 | 83 | 84 | 87 | 88 | 92 | 93 | 97 | 98 | 102 | 103 | 104 | -------------------------------------------------------------------------------- /markets.txt: -------------------------------------------------------------------------------- 1 | #渠道命名格式为 cn_首发_渠道名 其中:下杠“_”为字段之间的分隔符 “#”为注释符 命名中不要出现“-” 2 | 701_0_Offical#官网 3 | 7705_0_Huawei#华为 -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | //主工程 2 | include ':app' 3 | 4 | //工具库 5 | include ':libUtils' 6 | 7 | //基础组件 8 | include ':libView', ':libHttp', ':libFileProvider', ':libBaseFun' 9 | 10 | //业务层 11 | include ':bizCore' --------------------------------------------------------------------------------