() {
35 | @Override
36 | public void accept(Boolean granted) throws Exception {
37 | if (granted) {
38 | //获得了所有权限
39 | // textView.setAnimation(animationSet);
40 | } else {
41 | //至少有一个权限没有获得
42 | Toast.makeText(MyApplication.getInstance().getApplicationContext(), "请给应用赋予全部权限,否则无法使用", Toast.LENGTH_SHORT).show();
43 | finish();
44 | }
45 | }
46 | });
47 | }
48 |
49 | @Override
50 | public int getLayout() {
51 | return R.layout.activity_splash;
52 | }
53 |
54 | @Override
55 | public void onPointerCaptureChanged(boolean hasCapture) {
56 |
57 | }
58 |
59 | }
60 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable-v24/ic_launcher_foreground.xml:
--------------------------------------------------------------------------------
1 |
7 |
12 |
13 |
19 |
22 |
25 |
26 |
27 |
28 |
34 |
35 |
--------------------------------------------------------------------------------
/base_module/src/main/res/drawable-v24/ic_launcher_foreground.xml:
--------------------------------------------------------------------------------
1 |
7 |
12 |
13 |
19 |
22 |
25 |
26 |
27 |
28 |
34 |
35 |
--------------------------------------------------------------------------------
/login_module/src/main/res/drawable-v24/ic_launcher_foreground.xml:
--------------------------------------------------------------------------------
1 |
7 |
12 |
13 |
19 |
22 |
25 |
26 |
27 |
28 |
34 |
35 |
--------------------------------------------------------------------------------
/user_module/src/main/res/drawable-v24/ic_launcher_foreground.xml:
--------------------------------------------------------------------------------
1 |
7 |
12 |
13 |
19 |
22 |
25 |
26 |
27 |
28 |
34 |
35 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | 自己写的Android模块化框架,主要里面使用的有模块化,热更新thinker,最新的Android屏幕适配,ConstraintLayout的使用以及RxJava+Retrofit2.0+Butterknife+Picasso等
2 |
3 | 模块目录大概分类 base_module,login_module,user_module
4 |
5 | 
6 |
7 | base_module:主要用基础类,如存放网络请求,图片请求库,工具类等
8 |
9 | login_module:主要登录模块 user_module:用户模块 app:主模块
10 |
11 | mvp模式的引用:具体使用可以看图片中所对应的java代码
12 |
13 | 
14 |
15 | 热更新thinker :我使用的**enableProxyApplication = true **的情况
16 | 具体使用详见bugly中tinker以下链接:
17 |
18 | https://bugly.qq.com/docs/user-guide/instruction-manual-android-hotfix/#enableproxyapplication-true
19 |
20 | Android屏幕适配 使用的是 ***屏幕分辨率限定符与 smallestWidth 限定符适配原理***
21 |
22 | 
23 |
24 | ConstraintLayout在三个Fragment中使用将其一些属性以及链的使用如下图:
25 |
26 |   
27 |
28 | 模块化的一些配置:
29 |
30 | 首先在gradle.properties中添加 **isModule=false**
31 |
32 | 然后在每个module(app,login_module,user_module,base_module)中的build.gradle中添加
33 |
34 |
35 | if(isModule.toBoolean()){
36 | apply plugin: 'com.android.application'
37 | }else {
38 | apply plugin: 'com.android.library'
39 | }
40 |
41 |
42 |
43 | javaCompileOptions {
44 | annotationProcessorOptions {
45 | arguments = [AROUTER_MODULE_NAME: project.getName()]
46 | }
47 | }
48 |
49 | sourceSets {
50 | main {
51 | if (isModule.toBoolean()) {
52 | manifest.srcFile 'src/main/app/AndroidManifest.xml'
53 | } else {
54 | manifest.srcFile 'src/main/module/AndroidManifest.xml'
55 | }
56 | }
57 | }
58 |
59 |
60 | 在每个module中加入两个AndroidManifest.xml,一个是module清单文件,一个是作为主app清单文件
61 |
62 | 
63 |
64 | config.gradle:将其所有的依赖放到一起,然后在build.gradle中apply from:"config.gradle"引入
65 |
66 | 关于build.gradle 中api和implementation
67 |
68 | implementation就是使用了该命令编译的依赖,它仅仅对当前的Moudle提供使用其接口。
69 |
70 | api:和以前compile一样,其他moudle如果包含了此moudle就能直接使用其下的接口,不需要在引入。
71 |
72 | 
73 |
74 |
75 | 模块间的跳转用的阿里的ARouter
76 |
77 | https://github.com/alibaba/ARouter
78 |
79 |
80 |
81 |
82 |
83 |
84 |
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
24 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
39 |
40 |
45 |
48 |
49 |
50 |
51 |
--------------------------------------------------------------------------------
/user_module/src/main/res/layout/fragment_me.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
20 |
21 |
29 |
30 |
39 |
40 |
49 |
50 |
59 |
60 |
61 |
--------------------------------------------------------------------------------
/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 | set DIRNAME=%~dp0
12 | if "%DIRNAME%" == "" set DIRNAME=.
13 | set APP_BASE_NAME=%~n0
14 | set APP_HOME=%DIRNAME%
15 |
16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
17 | set DEFAULT_JVM_OPTS=
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 Windows variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 |
53 | :win9xME_args
54 | @rem Slurp the command line arguments.
55 | set CMD_LINE_ARGS=
56 | set _SKIP=2
57 |
58 | :win9xME_args_slurp
59 | if "x%~1" == "x" goto execute
60 |
61 | set CMD_LINE_ARGS=%*
62 |
63 | :execute
64 | @rem Setup the command line
65 |
66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
67 |
68 | @rem Execute Gradle
69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
70 |
71 | :end
72 | @rem End local scope for the variables with windows NT shell
73 | if "%ERRORLEVEL%"=="0" goto mainEnd
74 |
75 | :fail
76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
77 | rem the _cmd.exe /c_ return code!
78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
79 | exit /b 1
80 |
81 | :mainEnd
82 | if "%OS%"=="Windows_NT" endlocal
83 |
84 | :omega
85 |
--------------------------------------------------------------------------------
/user_module/build.gradle:
--------------------------------------------------------------------------------
1 | if (isModule.toBoolean()) {
2 | apply plugin: 'com.android.application'
3 | } else {
4 | apply plugin: 'com.android.library'
5 | }
6 |
7 | android {
8 | compileSdkVersion rootProject.ext.android.compileSdkVersion
9 | defaultConfig {
10 | if (isModule.toBoolean()){
11 | applicationId "com.hydinin.user_module"
12 | }
13 | minSdkVersion rootProject.ext.android.minSdkVersion
14 | targetSdkVersion rootProject.ext.android.targetSdkVersion
15 | versionCode 1
16 | versionName "1.0"
17 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
18 |
19 | javaCompileOptions {
20 | annotationProcessorOptions {
21 | arguments = [AROUTER_MODULE_NAME: project.getName()]
22 | }
23 | }
24 |
25 | sourceSets{
26 | main{
27 | if (isModule.toBoolean()){
28 | manifest.srcFile 'src/main/app/AndroidManifest.xml'
29 | }else{
30 | manifest.srcFile 'src/main/module/AndroidManifest.xml'
31 | }
32 | }
33 | }
34 | }
35 |
36 |
37 |
38 | signingConfigs {
39 | release {
40 | keyAlias 'hydinin'
41 | keyPassword 'hydinin123'
42 | storeFile file('../key/keystore.jks')
43 | storePassword 'hydinin123'
44 | }
45 | }
46 |
47 | buildTypes {
48 | release {
49 | minifyEnabled true
50 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
51 | signingConfig signingConfigs.release
52 | }
53 | }
54 |
55 | }
56 |
57 | dependencies {
58 | implementation fileTree(include: ['*.jar'], dir: 'libs')
59 | implementation rootProject.ext.supportLib["support-v4"]
60 | implementation rootProject.ext.supportLib["appcompat-v7"]
61 | implementation rootProject.ext.supportLib["constraint-layout"]
62 | implementation rootProject.ext.supportLib["design"]
63 | implementation rootProject.ext.supportLib["recyclerview-v7"]
64 | testImplementation rootProject.ext.test["junit"]
65 | androidTestImplementation rootProject.ext.test["runner"]
66 | androidTestImplementation rootProject.ext.test["espresso-core"]
67 |
68 | annotationProcessor rootProject.ext.arouter["arouter-compiler"]
69 | annotationProcessor rootProject.ext.butterknife["butterknife-compiler"]
70 |
71 | implementation project(':base_module')
72 | }
73 |
--------------------------------------------------------------------------------
/login_module/build.gradle:
--------------------------------------------------------------------------------
1 | if(isModule.toBoolean()){
2 | apply plugin: 'com.android.application'
3 | }else {
4 | apply plugin: 'com.android.library'
5 | }
6 | apply plugin: 'com.jakewharton.butterknife'
7 | android {
8 | compileSdkVersion rootProject.ext.android.compileSdkVersion
9 | defaultConfig {
10 | if (isModule.toBoolean()) {
11 | applicationId "com.hydinin.login_module"
12 | }
13 | minSdkVersion rootProject.ext.android.minSdkVersion
14 | targetSdkVersion rootProject.ext.android.targetSdkVersion
15 | versionCode 1
16 | versionName "1.0"
17 |
18 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
19 | javaCompileOptions {
20 | annotationProcessorOptions {
21 | arguments = [AROUTER_MODULE_NAME: project.getName()]
22 | }
23 | }
24 |
25 | sourceSets {
26 | main {
27 | if (isModule.toBoolean()) {
28 | manifest.srcFile 'src/main/app/AndroidManifest.xml'
29 | } else {
30 | manifest.srcFile 'src/main/module/AndroidManifest.xml'
31 | }
32 | }
33 | }
34 | }
35 |
36 | signingConfigs {
37 | release {
38 | keyAlias 'hydinin'
39 | keyPassword 'hydinin123'
40 | storeFile file('../key/keystore.jks')
41 | storePassword 'hydinin123'
42 | }
43 | }
44 |
45 | buildTypes {
46 | release {
47 | minifyEnabled true
48 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
49 | signingConfig signingConfigs.release
50 | }
51 | }
52 | }
53 |
54 | dependencies {
55 | implementation fileTree(include: ['*.jar'], dir: 'libs')
56 | implementation rootProject.ext.supportLib["support-v4"]
57 | implementation rootProject.ext.supportLib["appcompat-v7"]
58 | implementation rootProject.ext.supportLib["constraint-layout"]
59 | implementation rootProject.ext.supportLib["design"]
60 | implementation rootProject.ext.supportLib["recyclerview-v7"]
61 | testImplementation rootProject.ext.test["junit"]
62 | androidTestImplementation rootProject.ext.test["runner"]
63 | androidTestImplementation rootProject.ext.test["espresso-core"]
64 |
65 | annotationProcessor rootProject.ext.arouter["arouter-compiler"]
66 | annotationProcessor rootProject.ext.butterknife["butterknife-compiler"]
67 |
68 | implementation project(':base_module')
69 |
70 | }
71 |
--------------------------------------------------------------------------------
/app/src/main/java/com/hydinin/mesproject/SampleApplicationLike.java:
--------------------------------------------------------------------------------
1 | package com.hydinin.mesproject;
2 |
3 | import android.annotation.TargetApi;
4 | import android.app.Application;
5 | import android.content.Context;
6 | import android.content.Intent;
7 | import android.os.Build;
8 | import android.support.multidex.MultiDex;
9 | import android.util.Log;
10 |
11 | import com.alibaba.android.arouter.launcher.ARouter;
12 | import com.facebook.stetho.Stetho;
13 | import com.hydinin.base_module.utils.DisplayUtil;
14 | import com.tencent.bugly.Bugly;
15 | import com.tencent.bugly.beta.Beta;
16 | import com.tencent.tinker.entry.DefaultApplicationLike;
17 |
18 | public class SampleApplicationLike extends DefaultApplicationLike {
19 |
20 | public static final String TAG = "Tinker.SampleApplicationLike";
21 |
22 | public SampleApplicationLike(Application application, int tinkerFlags,
23 | boolean tinkerLoadVerifyFlag, long applicationStartElapsedTime,
24 | long applicationStartMillisTime, Intent tinkerResultIntent) {
25 | super(application, tinkerFlags, tinkerLoadVerifyFlag, applicationStartElapsedTime, applicationStartMillisTime, tinkerResultIntent);
26 | }
27 |
28 |
29 | @Override
30 | public void onCreate() {
31 | super.onCreate();
32 | // 这里实现SDK初始化,appId替换成你的在Bugly平台申请的appId
33 | // 调试时,将第三个参数改为true
34 | Bugly.init(getApplication(), "43bf2e25dc", false);
35 | if (true) { // 这两行必须写在init之前,否则这些配置在init过程中将无效
36 | ARouter.openLog(); // 打印日志
37 | ARouter.openDebug(); // 开启调试模式(如果在InstantRun模式下运行,必须开启调试模式!线上版本需要关闭,否则有安全风险)
38 | }
39 | Log.d("sssssssssApplication","sssssssssssss");
40 | ARouter.init(getApplication()); // 尽可能早,推荐在Application中初始化
41 |
42 | DisplayUtil.init(getApplication());
43 | Stetho.initializeWithDefaults(getApplication());
44 | }
45 |
46 |
47 | @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
48 | @Override
49 | public void onBaseContextAttached(Context base) {
50 | super.onBaseContextAttached(base);
51 | // you must install multiDex whatever tinker is installed!
52 | MultiDex.install(base);
53 |
54 | // 安装tinker
55 | // TinkerManager.installTinker(this); 替换成下面Bugly提供的方法
56 | Beta.installTinker(this);
57 | }
58 |
59 | @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
60 | public void registerActivityLifecycleCallback(Application.ActivityLifecycleCallbacks callbacks) {
61 | getApplication().registerActivityLifecycleCallbacks(callbacks);
62 | }
63 |
64 | }
--------------------------------------------------------------------------------
/app/tinker-support.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.tencent.bugly.tinker-support'
2 |
3 | def bakPath = file("${buildDir}/bakApk/")
4 |
5 | /**
6 | * 此处填写每次构建生成的基准包目录
7 | */
8 | //def baseApkDir = "app-1226-15-03-59"
9 | def baseApkDir = "app-1226-16-53-56"
10 |
11 | /**
12 | * 对于插件各参数的详细解析请参考
13 | */
14 | tinkerSupport {
15 |
16 | // 开启tinker-support插件,默认值true
17 | enable = true
18 |
19 | // 指定归档目录,默认值当前module的子目录tinker
20 | autoBackupApkDir = "${bakPath}"
21 |
22 | // 是否启用覆盖tinkerPatch配置功能,默认值false
23 | // 开启后tinkerPatch配置不生效,即无需添加tinkerPatch
24 | overrideTinkerPatchConfiguration = true
25 |
26 | // 编译补丁包时,必需指定基线版本的apk,默认值为空
27 | // 如果为空,则表示不是进行补丁包的编译
28 | // @{link tinkerPatch.oldApk }
29 | baseApk = "${bakPath}/${baseApkDir}/app-release.apk"
30 |
31 | // 对应tinker插件applyMapping
32 | baseApkProguardMapping = "${bakPath}/${baseApkDir}/app-release-mapping.txt"
33 |
34 | // 对应tinker插件applyResourceMapping
35 | baseApkResourceMapping = "${bakPath}/${baseApkDir}/app-release-R.txt"
36 |
37 | // 构建基准包和补丁包都要指定不同的tinkerId,并且必须保证唯一性
38 | tinkerId = "base-1.0.1"
39 |
40 | // 构建多渠道补丁时使用
41 | // buildAllFlavorsDir = "${bakPath}/${baseApkDir}"
42 |
43 | // 是否启用加固模式,默认为false.(tinker-spport 1.0.7起支持)
44 | // isProtectedApp = true
45 |
46 | // 是否开启反射Application模式
47 | enableProxyApplication = true
48 |
49 | // 是否支持新增非export的Activity(注意:设置为true才能修改AndroidManifest文件)
50 | supportHotplugComponent = true
51 |
52 | }
53 |
54 | /**
55 | * 一般来说,我们无需对下面的参数做任何的修改
56 | * 对于各参数的详细介绍请参考:
57 | * https://github.com/Tencent/tinker/wiki/Tinker-%E6%8E%A5%E5%85%A5%E6%8C%87%E5%8D%97
58 | */
59 | tinkerPatch {
60 | //oldApk ="${bakPath}/${appName}/app-release.apk"
61 | ignoreWarning = false
62 | useSign = true
63 | dex {
64 | dexMode = "jar"
65 | pattern = ["classes*.dex"]
66 | loader = []
67 | }
68 | lib {
69 | pattern = ["lib/*/*.so"]
70 | }
71 |
72 | res {
73 | pattern = ["res/*", "r/*", "assets/*", "resources.arsc", "AndroidManifest.xml"]
74 | ignoreChange = []
75 | largeModSize = 100
76 | }
77 |
78 | packageConfig {
79 | }
80 | sevenZip {
81 | zipArtifact = "com.tencent.mm:SevenZip:1.1.10"
82 | // path = "/usr/local/bin/7za"
83 | }
84 | buildConfig {
85 | keepDexApply = false
86 | //tinkerId = "1.0.1-base"
87 | //applyMapping = "${bakPath}/${appName}/app-release-mapping.txt" // 可选,设置mapping文件,建议保持旧apk的proguard混淆方式
88 | //applyResourceMapping = "${bakPath}/${appName}/app-release-R.txt" // 可选,设置R.txt文件,通过旧apk文件保持ResId的分配
89 | }
90 | }
91 |
92 |
--------------------------------------------------------------------------------
/base_module/src/main/java/com/hydinin/base_module/base/RxBaseActivity.java:
--------------------------------------------------------------------------------
1 | package com.hydinin.base_module.base;
2 |
3 | import android.os.Bundle;
4 | import android.support.annotation.CallSuper;
5 | import android.support.annotation.CheckResult;
6 | import android.support.annotation.NonNull;
7 | import android.support.annotation.Nullable;
8 | import android.support.v7.app.AppCompatActivity;
9 |
10 | import com.trello.rxlifecycle2.LifecycleProvider;
11 | import com.trello.rxlifecycle2.LifecycleTransformer;
12 | import com.trello.rxlifecycle2.RxLifecycle;
13 | import com.trello.rxlifecycle2.android.ActivityEvent;
14 | import com.trello.rxlifecycle2.android.RxLifecycleAndroid;
15 |
16 | import io.reactivex.Observable;
17 | import io.reactivex.subjects.BehaviorSubject;
18 |
19 | public class RxBaseActivity extends AppCompatActivity implements LifecycleProvider {
20 |
21 | private final BehaviorSubject lifecycleSubject = BehaviorSubject.create();
22 |
23 | @Override
24 | @NonNull
25 | @CheckResult
26 | public final Observable lifecycle() {
27 | return lifecycleSubject.hide();
28 | }
29 |
30 | @Override
31 | @NonNull
32 | @CheckResult
33 | public final LifecycleTransformer bindUntilEvent(@NonNull ActivityEvent event) {
34 | return RxLifecycle.bindUntilEvent(lifecycleSubject, event);
35 | }
36 |
37 | @Override
38 | @NonNull
39 | @CheckResult
40 | public final LifecycleTransformer bindToLifecycle() {
41 | return RxLifecycleAndroid.bindActivity(lifecycleSubject);
42 | }
43 |
44 | @Override
45 | @CallSuper
46 | protected void onCreate(@Nullable Bundle savedInstanceState) {
47 | super.onCreate(savedInstanceState);
48 | lifecycleSubject.onNext(ActivityEvent.CREATE);
49 | }
50 |
51 | @Override
52 | @CallSuper
53 | protected void onStart() {
54 | super.onStart();
55 | lifecycleSubject.onNext(ActivityEvent.START);
56 | }
57 |
58 | @Override
59 | @CallSuper
60 | protected void onResume() {
61 | super.onResume();
62 | lifecycleSubject.onNext(ActivityEvent.RESUME);
63 | }
64 |
65 | @Override
66 | @CallSuper
67 | protected void onPause() {
68 | lifecycleSubject.onNext(ActivityEvent.PAUSE);
69 | super.onPause();
70 | }
71 |
72 | @Override
73 | @CallSuper
74 | protected void onStop() {
75 | lifecycleSubject.onNext(ActivityEvent.STOP);
76 | super.onStop();
77 | }
78 |
79 | @Override
80 | @CallSuper
81 | protected void onDestroy() {
82 | lifecycleSubject.onNext(ActivityEvent.DESTROY);
83 | super.onDestroy();
84 | }
85 | }
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 | apply from: 'tinker-support.gradle'
3 | // 多渠道使用walle示例(注:多渠道使用)
4 | apply from: 'multiple-channel.gradle'
5 |
6 | android {
7 | compileSdkVersion rootProject.ext.android.compileSdkVersion
8 | defaultConfig {
9 | applicationId "com.hydinin.mesproject"
10 | minSdkVersion rootProject.ext.android.minSdkVersion
11 | targetSdkVersion rootProject.ext.android.targetSdkVersion
12 | versionCode 2
13 | versionName "1.0.1"
14 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
15 | externalNativeBuild {
16 | cmake {
17 | cppFlags "-frtti -fexceptions"
18 | }
19 | }
20 |
21 | javaCompileOptions {
22 | annotationProcessorOptions {
23 | arguments = [AROUTER_MODULE_NAME: project.getName()]
24 | }
25 | }
26 | }
27 |
28 | signingConfigs {
29 | release {
30 | keyAlias 'hydinin'
31 | keyPassword 'hydinin123'
32 | storeFile file('../key/keystore.jks')
33 | storePassword 'hydinin123'
34 | }
35 | }
36 |
37 | buildTypes {
38 | release {
39 | minifyEnabled true
40 | shrinkResources true
41 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
42 | signingConfig signingConfigs.release
43 | }
44 | }
45 |
46 | externalNativeBuild {
47 | cmake {
48 | path "CMakeLists.txt"
49 | }
50 | }
51 | }
52 |
53 | dependencies {
54 | implementation fileTree(include: ['*.jar'], dir: 'libs')
55 | implementation rootProject.ext.supportLib["support-v4"]
56 | implementation rootProject.ext.supportLib["appcompat-v7"]
57 | implementation rootProject.ext.supportLib["constraint-layout"]
58 | implementation rootProject.ext.supportLib["design"]
59 | implementation rootProject.ext.supportLib["recyclerview-v7"]
60 | implementation 'com.android.support.constraint:constraint-layout:1.1.3'
61 | testImplementation rootProject.ext.test["junit"]
62 | androidTestImplementation rootProject.ext.test["runner"]
63 | androidTestImplementation rootProject.ext.test["espresso-core"]
64 |
65 | annotationProcessor rootProject.ext.arouter["arouter-compiler"]
66 | annotationProcessor rootProject.ext.butterknife["butterknife-compiler"]
67 |
68 | implementation rootProject.ext.bugly["thinker"]
69 | implementation rootProject.ext.bugly["bugly"]
70 | implementation rootProject.ext.bugly["bugly-report"]
71 | implementation rootProject.ext.multidex["multidex"]
72 | implementation rootProject.ext.walle["walle"]
73 |
74 |
75 | implementation project(':base_module')
76 | implementation project(':login_module')
77 | implementation project(':user_module')
78 | }
79 |
--------------------------------------------------------------------------------
/login_module/src/main/java/com/hydinin/login_module/IpSaveActivity.java:
--------------------------------------------------------------------------------
1 | package com.hydinin.login_module;
2 |
3 | import android.os.Bundle;
4 | import android.util.Log;
5 | import android.view.View;
6 | import android.widget.EditText;
7 | import android.widget.TextView;
8 | import android.widget.Toast;
9 |
10 | import com.hydinin.base_module.base.BaseActivity;
11 | import com.hydinin.base_module.constant.Constant;
12 | import com.hydinin.base_module.utils.SPUtil;
13 | import com.hydinin.base_module.utils.ToastUtil;
14 | import com.hydinin.base_module.utils.UIHelper;
15 |
16 | import butterknife.BindView;
17 | import butterknife.OnClick;
18 | import okhttp3.HttpUrl;
19 |
20 | public class IpSaveActivity extends BaseActivity {
21 |
22 | @BindView(R2.id.ipEdit)
23 | EditText ipEdit;
24 | @BindView(R2.id.portEdit)
25 | EditText portEdit;
26 | @BindView(R2.id.saveIP)
27 | TextView saveIP;
28 |
29 | @Override
30 | protected void onCreate(Bundle savedInstanceState) {
31 | super.onCreate(savedInstanceState);
32 | Log.i("sssssIpActivity","onCreate");
33 | String ip = (String) SPUtil.get(this, Constant.IpInfo.IP, "");
34 | String port = (String) SPUtil.get(this, Constant.IpInfo.PORT, "");
35 | ipEdit.setText(ip);
36 | portEdit.setText(port);
37 | }
38 |
39 | @OnClick({R2.id.saveIP})
40 | void setOnClick(View view) {
41 | int id = view.getId();
42 | if (id == R.id.saveIP) {
43 | String ip = ipEdit.getText().toString().trim();
44 | String port = portEdit.getText().toString().trim();
45 | String url="http://"+ip+":"+port+"/portal/";
46 | HttpUrl httpUrl = HttpUrl.parse(url);
47 | if (httpUrl == null) {
48 | ToastUtil.show(this.getApplicationContext(),"您输入的ip或端口无效");
49 | }else {
50 | SPUtil.putAndApply(this, Constant.IpInfo.IP, ip);
51 | SPUtil.putAndApply(this, Constant.IpInfo.PORT, port);
52 | Toast.makeText(this,"保存成功",Toast.LENGTH_SHORT).show();
53 | this.finish();
54 | }
55 | }
56 | }
57 |
58 | @Override
59 | protected void onRestart() {
60 | super.onRestart();
61 | Log.i("sssssIpActivity","onRestart");
62 | }
63 |
64 | @Override
65 | protected void onStart() {
66 | super.onStart();
67 | Log.i("sssssIpActivity","onStart");
68 | }
69 |
70 | @Override
71 | protected void onResume() {
72 | super.onResume();
73 | Log.i("sssssIpActivity","onResume");
74 | }
75 |
76 | @Override
77 | protected void onPause() {
78 | super.onPause();
79 | Log.i("sssssIpActivity","onPause");
80 | }
81 |
82 | @Override
83 | protected void onStop() {
84 | super.onStop();
85 | Log.i("sssssIpActivity","onStop");
86 | }
87 |
88 | @Override
89 | protected void onDestroy() {
90 | super.onDestroy();
91 | Log.i("sssssIpActivity","onDestroy");
92 | }
93 |
94 | @Override
95 | public int getLayout() {
96 | return R.layout.activity_ip_save;
97 | }
98 | }
99 |
--------------------------------------------------------------------------------
/base_module/src/main/java/com/hydinin/base_module/utils/UnicodeUtils.java:
--------------------------------------------------------------------------------
1 | package com.hydinin.base_module.utils;
2 |
3 | /**
4 | * Created by Android Studio
5 | * Project:AndroidDemo
6 | * Author:httvc
7 | * Email:jfjie2013@163.com
8 | * Date:2017/5/24.
9 | */
10 |
11 | public class UnicodeUtils {
12 | /**
13 | * 把含有Unicode 的字符串可视化
14 | *
15 | * @param ori
16 | * @return
17 | */
18 | public static String convertUnicode(String ori) {
19 | char aChar;
20 | int len = ori.length();
21 | StringBuffer outBuffer = new StringBuffer(len);
22 | for (int x = 0; x < len; ) {
23 | aChar = ori.charAt(x++);
24 | if (aChar == '\\') {
25 | aChar = ori.charAt(x++);
26 | if (aChar == 'u') {
27 | // Read the xxxx
28 | int value = 0;
29 | for (int i = 0; i < 4; i++) {
30 | aChar = ori.charAt(x++);
31 | switch (aChar) {
32 | case '0':
33 | case '1':
34 | case '2':
35 | case '3':
36 | case '4':
37 | case '5':
38 | case '6':
39 | case '7':
40 | case '8':
41 | case '9':
42 | value = (value << 4) + aChar - '0';
43 | break;
44 | case 'a':
45 | case 'b':
46 | case 'c':
47 | case 'd':
48 | case 'e':
49 | case 'f':
50 | value = (value << 4) + 10 + aChar - 'a';
51 | break;
52 | case 'A':
53 | case 'B':
54 | case 'C':
55 | case 'D':
56 | case 'E':
57 | case 'F':
58 | value = (value << 4) + 10 + aChar - 'A';
59 | break;
60 | default:
61 | throw new IllegalArgumentException(
62 | "Malformed \\uxxxx encoding.");
63 | }
64 | }
65 | outBuffer.append((char) value);
66 | } else {
67 | if (aChar == 't')
68 | aChar = '\t';
69 | else if (aChar == 'r')
70 | aChar = '\r';
71 | else if (aChar == 'n')
72 | aChar = '\n';
73 | else if (aChar == 'f')
74 | aChar = '\f';
75 | outBuffer.append(aChar);
76 | }
77 | } else
78 | outBuffer.append(aChar);
79 |
80 | }
81 | return outBuffer.toString();
82 | }
83 |
84 | }
85 |
--------------------------------------------------------------------------------
/base_module/build.gradle:
--------------------------------------------------------------------------------
1 | if(isModule.toBoolean()){
2 | apply plugin: 'com.android.application'
3 | }else {
4 | apply plugin: 'com.android.library'
5 | }
6 | apply plugin: 'com.jakewharton.butterknife'
7 |
8 | android {
9 | compileSdkVersion rootProject.ext.android.compileSdkVersion
10 | defaultConfig {
11 | if (isModule.toBoolean()){
12 | applicationId "com.hydinin.base_module"
13 | }
14 | minSdkVersion rootProject.ext.android.minSdkVersion
15 | targetSdkVersion rootProject.ext.android.targetSdkVersion
16 | versionCode 1
17 | versionName "1.0"
18 |
19 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
20 | javaCompileOptions {
21 | annotationProcessorOptions {
22 | arguments = [AROUTER_MODULE_NAME: project.getName()]
23 | }
24 | }
25 |
26 | ndk {
27 | //设置支持的SO库架构
28 | abiFilters 'armeabi' //, 'x86', 'armeabi-v7a', 'x86_64', 'arm64-v8a'
29 | }
30 |
31 |
32 | }
33 |
34 | signingConfigs {
35 | release {
36 | keyAlias 'hydinin'
37 | keyPassword 'hydinin123'
38 | storeFile file('../key/keystore.jks')
39 | storePassword 'hydinin123'
40 | }
41 | }
42 |
43 | buildTypes {
44 | release {
45 | minifyEnabled true
46 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
47 | signingConfig signingConfigs.release
48 | }
49 | }
50 |
51 |
52 | buildTypes {
53 | release {
54 | minifyEnabled true
55 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
56 |
57 | }
58 | }
59 |
60 | }
61 |
62 | dependencies {
63 | implementation fileTree(dir: 'libs', include: ['*.jar'])
64 | implementation rootProject.ext.supportLib["appcompat-v7"]
65 | testImplementation rootProject.ext.test["junit"]
66 | androidTestImplementation rootProject.ext.test["runner"]
67 | androidTestImplementation rootProject.ext.test["espresso-core"]
68 |
69 | api rootProject.ext.arouter["arouter-api"]
70 | annotationProcessor rootProject.ext.arouter["arouter-compiler"]
71 |
72 | api rootProject.ext.retrofit["retrofit"]
73 | api rootProject.ext.retrofit["retrofit-gson"]
74 | api rootProject.ext.retrofit["retrofit-adapter"]
75 | api rootProject.ext.rxJava["rxJava"]
76 | api rootProject.ext.rxJava["rxAndroid"]
77 | api rootProject.ext.okhttp["logging-interceptor"]
78 | api rootProject.ext.rxLifecycle["rxlifecycle"]
79 | api rootProject.ext.rxLifecycle["rxlifecycle-components"]
80 |
81 | api rootProject.ext.butterknife["butterknife"]
82 | annotationProcessor rootProject.ext.butterknife["butterknife-compiler"]
83 |
84 | api rootProject.ext.eventbus["eventbus"]
85 |
86 | api rootProject.ext.stetho["stetho"]
87 | api rootProject.ext.stetho["stetho-okhttp3"]
88 |
89 | api rootProject.ext.rxpermissions["rxpermissions"]
90 | }
91 |
--------------------------------------------------------------------------------
/base_module/src/main/java/com/hydinin/base_module/base/RxBaseFragment.java:
--------------------------------------------------------------------------------
1 | package com.hydinin.base_module.base;
2 |
3 | import android.os.Bundle;
4 | import android.support.annotation.CheckResult;
5 | import android.support.annotation.NonNull;
6 | import android.support.annotation.Nullable;
7 | import android.support.v4.app.Fragment;
8 | import android.view.View;
9 |
10 | import com.trello.rxlifecycle2.LifecycleProvider;
11 | import com.trello.rxlifecycle2.LifecycleTransformer;
12 | import com.trello.rxlifecycle2.RxLifecycle;
13 | import com.trello.rxlifecycle2.android.FragmentEvent;
14 | import com.trello.rxlifecycle2.android.RxLifecycleAndroid;
15 |
16 | import io.reactivex.Observable;
17 | import io.reactivex.subjects.BehaviorSubject;
18 |
19 |
20 | public class RxBaseFragment extends Fragment implements LifecycleProvider {
21 |
22 | private final BehaviorSubject lifecycleSubject = BehaviorSubject.create();
23 |
24 | @Override
25 | @NonNull
26 | @CheckResult
27 | public final Observable lifecycle() {
28 | return lifecycleSubject.hide();
29 | }
30 |
31 | @Override
32 | @NonNull
33 | @CheckResult
34 | public final LifecycleTransformer bindUntilEvent(@NonNull FragmentEvent event) {
35 | return RxLifecycle.bindUntilEvent(lifecycleSubject, event);
36 | }
37 |
38 | @Override
39 | @NonNull
40 | @CheckResult
41 | public final LifecycleTransformer bindToLifecycle() {
42 | return RxLifecycleAndroid.bindFragment(lifecycleSubject);
43 | }
44 |
45 | @Override
46 | public void onAttach(android.app.Activity activity) {
47 | super.onAttach(activity);
48 | lifecycleSubject.onNext(FragmentEvent.ATTACH);
49 | }
50 |
51 | @Override
52 | public void onCreate(@Nullable Bundle savedInstanceState) {
53 | super.onCreate(savedInstanceState);
54 | lifecycleSubject.onNext(FragmentEvent.CREATE);
55 | }
56 |
57 | @Override
58 | public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
59 | super.onViewCreated(view, savedInstanceState);
60 | lifecycleSubject.onNext(FragmentEvent.CREATE_VIEW);
61 | }
62 |
63 | @Override
64 | public void onStart() {
65 | super.onStart();
66 | lifecycleSubject.onNext(FragmentEvent.START);
67 | }
68 |
69 | @Override
70 | public void onResume() {
71 | super.onResume();
72 | lifecycleSubject.onNext(FragmentEvent.RESUME);
73 | }
74 |
75 | @Override
76 | public void onPause() {
77 | lifecycleSubject.onNext(FragmentEvent.PAUSE);
78 | super.onPause();
79 | }
80 |
81 | @Override
82 | public void onStop() {
83 | lifecycleSubject.onNext(FragmentEvent.STOP);
84 | super.onStop();
85 | }
86 |
87 | @Override
88 | public void onDestroyView() {
89 | lifecycleSubject.onNext(FragmentEvent.DESTROY_VIEW);
90 | super.onDestroyView();
91 | }
92 |
93 | @Override
94 | public void onDestroy() {
95 | lifecycleSubject.onNext(FragmentEvent.DESTROY);
96 | super.onDestroy();
97 | }
98 |
99 | @Override
100 | public void onDetach() {
101 | lifecycleSubject.onNext(FragmentEvent.DETACH);
102 | super.onDetach();
103 | }
104 | }
105 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/fragment_order.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
20 |
28 |
38 |
48 |
60 |
69 |
76 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/fragment_home.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
17 |
24 |
32 |
40 |
48 |
56 |
57 |
65 |
72 |
78 |
--------------------------------------------------------------------------------
/base_module/src/main/java/com/hydinin/base_module/base/BaseFragment.java:
--------------------------------------------------------------------------------
1 | package com.hydinin.base_module.base;
2 |
3 | import android.content.Context;
4 | import android.os.Bundle;
5 | import android.support.annotation.IdRes;
6 | import android.support.annotation.Nullable;
7 | import android.view.LayoutInflater;
8 | import android.view.View;
9 | import android.view.ViewGroup;
10 |
11 | import com.hydinin.base_module.R;
12 | import com.hydinin.base_module.widget.TitleView;
13 |
14 |
15 | public abstract class BaseFragment extends RxBaseFragment {
16 | private View rootView;
17 | private boolean created;
18 |
19 | @Override
20 | public void onAttach(Context context) {
21 | super.onAttach(context);
22 | // mActivity = (BaseFragmentActivity) context;
23 | }
24 |
25 | @Override
26 | public void onViewCreated(View view, Bundle savedInstanceState) {
27 | super.onViewCreated(view, savedInstanceState);
28 | created = true;
29 | }
30 |
31 | @Override
32 | public void onActivityCreated(@Nullable Bundle savedInstanceState) {
33 | super.onActivityCreated(savedInstanceState);
34 | }
35 |
36 | @Nullable
37 | @Override
38 | public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
39 | if (rootView == null) {
40 | rootView = inflater.inflate(getLayout(), null);
41 | onBaseCreate(savedInstanceState);
42 | }
43 | ViewGroup parent = (ViewGroup) rootView.getParent();
44 | if (parent != null)
45 | parent.removeView(rootView);
46 | return rootView;
47 | }
48 |
49 |
50 | private TitleView titleView;
51 |
52 | public TitleView getTitleView() {
53 | return titleView == null ? new TitleView(getActivity(), (View) findViewById(R.id.header)) : titleView;
54 | }
55 |
56 |
57 | private boolean isDestory = false;
58 |
59 | @Override
60 | public void onDestroy() {
61 | super.onDestroy();
62 | isDestory = true;
63 | }
64 |
65 | public boolean isDestory() {
66 | return isDestory;
67 | }
68 |
69 |
70 | public View findViewById(@IdRes int id) {
71 | if (rootView != null) {
72 | return rootView.findViewById(id);
73 | } else {
74 | throw new NullPointerException("rootView is null, run getLayout() is ture ?");
75 | }
76 | }
77 |
78 | /**
79 | * 页面第一次加载时杂乱操作放在这里执行,非子线程
80 | */
81 | public void onLoad() {
82 | }
83 |
84 | public String getPageTitle() {
85 | return null;
86 | }
87 |
88 | @Override
89 | public void onResume() {
90 | super.onResume();
91 | // 判断当前fragment是否显示
92 | if (getUserVisibleHint()) {
93 | if (created) {
94 | onLoad();
95 | created = false;
96 | }
97 | }
98 | }
99 |
100 | @Override
101 | public void setUserVisibleHint(boolean isVisibleToUser) {
102 | super.setUserVisibleHint(isVisibleToUser);
103 | // 每次切换fragment时调用的方法
104 | if (isVisibleToUser) {
105 | if (created) {
106 | onLoad();
107 | created = false;
108 | }
109 | }
110 | }
111 |
112 | public boolean isCreated() {
113 | return created;
114 | }
115 |
116 | public void setCreated(boolean created) {
117 | this.created = created;
118 | }
119 |
120 | @Override
121 | public void onDestroyView() {
122 | super.onDestroyView();
123 | }
124 |
125 | @Override
126 | public void onDetach() {
127 | super.onDetach();
128 | }
129 |
130 | public abstract void onBaseCreate(Bundle savedInstanceState);
131 |
132 | public abstract int getLayout();
133 |
134 | public View getRootView() {
135 | return rootView;
136 | }
137 |
138 |
139 | }
140 |
--------------------------------------------------------------------------------
/base_module/src/main/java/com/hydinin/base_module/utils/OSUtils.java:
--------------------------------------------------------------------------------
1 | package com.hydinin.base_module.utils;
2 |
3 | import android.os.Build;
4 | import android.text.TextUtils;
5 |
6 | import java.io.BufferedReader;
7 | import java.io.IOException;
8 | import java.io.InputStreamReader;
9 |
10 | public class OSUtils {
11 | public static final String ROM_MIUI = "MIUI";
12 | public static final String ROM_EMUI = "EMUI";
13 | public static final String ROM_FLYME = "FLYME";
14 | public static final String ROM_OPPO = "OPPO";
15 | public static final String ROM_SMARTISAN = "SMARTISAN";
16 | public static final String ROM_VIVO = "VIVO";
17 | public static final String ROM_QIKU = "QIKU";
18 |
19 | private static final String KEY_VERSION_MIUI = "ro.miui.ui.version.name";
20 | private static final String KEY_VERSION_EMUI = "ro.build.version.emui";
21 | private static final String KEY_VERSION_OPPO = "ro.build.version.opporom";
22 | private static final String KEY_VERSION_SMARTISAN = "ro.smartisan.version";
23 | private static final String KEY_VERSION_VIVO = "ro.vivo.os.version";
24 |
25 | private static String sName;
26 | private static String sVersion;
27 |
28 | public static boolean isEmui() {
29 | return check(ROM_EMUI);
30 | }
31 |
32 | public static boolean isMiui() {
33 | return check(ROM_MIUI);
34 | }
35 |
36 | public static boolean isVivo() {
37 | return check(ROM_VIVO);
38 | }
39 |
40 | public static boolean isOppo() {
41 | return check(ROM_OPPO);
42 | }
43 |
44 | public static boolean isFlyme() {
45 | return check(ROM_FLYME);
46 | }
47 |
48 | public static boolean is360() {
49 | return check(ROM_QIKU) || check("360");
50 | }
51 |
52 | public static boolean isSmartisan() {
53 | return check(ROM_SMARTISAN);
54 | }
55 |
56 | public static String getName() {
57 | if (sName == null) {
58 | check("");
59 | }
60 | return sName;
61 | }
62 |
63 | public static String getVersion() {
64 | if (sVersion == null) {
65 | check("");
66 | }
67 | return sVersion;
68 | }
69 |
70 | public static boolean check(String rom) {
71 | if (sName != null) {
72 | return sName.equals(rom);
73 | }
74 |
75 | if (!TextUtils.isEmpty(sVersion = getProp(KEY_VERSION_MIUI))) {
76 | sName = ROM_MIUI;
77 | } else if (!TextUtils.isEmpty(sVersion = getProp(KEY_VERSION_EMUI))) {
78 | sName = ROM_EMUI;
79 | } else if (!TextUtils.isEmpty(sVersion = getProp(KEY_VERSION_OPPO))) {
80 | sName = ROM_OPPO;
81 | } else if (!TextUtils.isEmpty(sVersion = getProp(KEY_VERSION_VIVO))) {
82 | sName = ROM_VIVO;
83 | } else if (!TextUtils.isEmpty(sVersion = getProp(KEY_VERSION_SMARTISAN))) {
84 | sName = ROM_SMARTISAN;
85 | } else {
86 | sVersion = Build.DISPLAY;
87 | if (sVersion.toUpperCase().contains(ROM_FLYME)) {
88 | sName = ROM_FLYME;
89 | } else {
90 | sVersion = Build.UNKNOWN;
91 | sName = Build.MANUFACTURER.toUpperCase();
92 | }
93 | }
94 | return sName.equals(rom);
95 | }
96 |
97 | public static String getProp(String name) {
98 | String line = null;
99 | BufferedReader input = null;
100 | try {
101 | Process p = Runtime.getRuntime().exec("getprop " + name);
102 | input = new BufferedReader(new InputStreamReader(p.getInputStream()), 1024);
103 | line = input.readLine();
104 | input.close();
105 | } catch (IOException ex) {
106 | return null;
107 | } finally {
108 | if (input != null) {
109 | try {
110 | input.close();
111 | } catch (IOException e) {
112 | e.printStackTrace();
113 | }
114 | }
115 | }
116 | return line;
117 | }
118 | }
119 |
--------------------------------------------------------------------------------
/app/src/main/java/com/hydinin/mesproject/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.hydinin.mesproject;
2 |
3 | import android.os.Build;
4 | import android.support.design.widget.TabLayout;
5 | import android.support.v4.app.Fragment;
6 | import android.support.v7.app.AppCompatActivity;
7 | import android.os.Bundle;
8 | import android.view.View;
9 | import android.widget.ImageView;
10 | import android.widget.TextView;
11 |
12 | import com.alibaba.android.arouter.facade.annotation.Route;
13 | import com.hydinin.base_module.arouter.ARouteConstant;
14 | import com.hydinin.base_module.base.BaseActivity;
15 | import com.hydinin.base_module.utils.StatusBarUtil;
16 | import com.hydinin.mesproject.widget.HomeGenerator;
17 |
18 | import org.greenrobot.eventbus.EventBus;
19 |
20 | import butterknife.BindView;
21 |
22 | @Route(path = ARouteConstant.app_activity_Main)
23 | public class MainActivity extends BaseActivity {
24 | @BindView(R.id.bottom_tab_layout)
25 | TabLayout mTabLayout;
26 | private Fragment[] mFragmensts;
27 | // Used to load the 'native-lib' library on application startup.
28 | static {
29 | System.loadLibrary("native-lib");
30 | }
31 |
32 | /**
33 | * A native method that is implemented by the 'native-lib' native library,
34 | * which is packaged with this application.
35 | */
36 | public native String stringFromJNI();
37 |
38 | @Override
39 | protected void onCreate(Bundle savedInstanceState) {
40 | super.onCreate(savedInstanceState);
41 | initTabLayout();
42 | TextView tv = (TextView) findViewById(R.id.sample_text);
43 | tv.setText(stringFromJNI());
44 | // Example of a call to a native method
45 |
46 | }
47 |
48 | @Override
49 | public int getLayout() {
50 | return R.layout.activity_main;
51 | }
52 |
53 | private void onTabItemSelected(int position) {
54 | Fragment fragment = null;
55 | switch (position) {
56 | case 0:
57 | fragment = mFragmensts[0];
58 | break;
59 | case 1:
60 | fragment = mFragmensts[1];
61 | break;
62 | case 2:
63 | fragment = mFragmensts[2];
64 | break;
65 | }
66 | for (int i = 0; i < mFragmensts.length; i++) {
67 | getSupportFragmentManager().beginTransaction().hide(mFragmensts[i]).commit();
68 | }
69 | if (fragment != null) {
70 | // getSupportFragmentManager().beginTransaction().replace(R.id.home_container, fragment).commit();
71 | getSupportFragmentManager().beginTransaction().show(fragment).commit();
72 | }
73 | }
74 |
75 | private void initTabLayout() {
76 | mFragmensts = HomeGenerator.getFragments();
77 | for (int i = 0; i < mFragmensts.length; i++) {
78 | getSupportFragmentManager().beginTransaction().add(R.id.home_container, mFragmensts[i]).commit();
79 | }
80 | getSupportFragmentManager().beginTransaction().show(mFragmensts[0]).commit();
81 | mTabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
82 | @Override
83 | public void onTabSelected(TabLayout.Tab tab) {
84 | onTabItemSelected(tab.getPosition());
85 | // Tab 选中之后,改变各个Tab的状态
86 | for (int i = 0; i < mTabLayout.getTabCount(); i++) {
87 | View view = mTabLayout.getTabAt(i).getCustomView();
88 | ImageView icon = (ImageView) view.findViewById(R.id.tab_content_image1);
89 | TextView text = (TextView) view.findViewById(R.id.tab_content_text);
90 | if (i == tab.getPosition()) { // 选中状态
91 | // icon.setImageResource(HomeGenerator.mTabResPressed[i]);
92 | // text.setTextColor(getResources().getColor(R.color.green));
93 | icon.setVisibility(View.VISIBLE);
94 | } else {// 未选中状态
95 | icon.setVisibility(View.INVISIBLE);
96 | // icon.setImageResource(HomeGenerator.mTabRes[i]);
97 | // text.setTextColor(getResources().getColor(R.color.color_171717));
98 | }
99 | }
100 | }
101 |
102 | @Override
103 | public void onTabUnselected(TabLayout.Tab tab) {
104 |
105 | }
106 |
107 | @Override
108 | public void onTabReselected(TabLayout.Tab tab) {
109 |
110 | }
111 | });
112 | // 提供自定义的布局添加Tab
113 | for (int i = 0; i < 3; i++) {
114 | mTabLayout.addTab(mTabLayout.newTab().setCustomView(HomeGenerator.getTabView(this, i)));
115 | }
116 | }
117 |
118 | }
119 |
--------------------------------------------------------------------------------
/config.gradle:
--------------------------------------------------------------------------------
1 | ext {
2 |
3 | android = [
4 | compileSdkVersion : 28,
5 | buildToolsVersion : "28.0.0",
6 | minSdkVersion : 19,
7 | targetSdkVersion : 28
8 |
9 |
10 | ]
11 |
12 | dependVersion = [
13 | rxJava : "2.2.4",
14 | rxAndroid : "2.1.0",
15 | retrofit : "2.5.0",
16 | logging_interceptor : "3.12.1",
17 | rxlifecycle : "3.0.0",
18 | supportVersion : "28.0.0",
19 | constraint_layout : "1.1.3",
20 | junit : "4.12",
21 | runner : "1.0.2",
22 | espresso_core : "3.0.2",
23 | arouter_api : "1.4.1",
24 | arouter_compiler : "1.2.2",
25 | rxlifecycle : "2.2.1",
26 | butterknife : "8.8.1",
27 | evenbus : "3.1.1",
28 | multidex : "1.0.3",
29 | walle : "1.1.6",
30 | stetho : "1.5.0",
31 | rxpermissions : "0.10.2",
32 |
33 | ]
34 |
35 | supportLib = [
36 | "support-v4" : "com.android.support:support-v4:$dependVersion.supportVersion",
37 | "appcompat-v7" : "com.android.support:appcompat-v7:$dependVersion.supportVersion",
38 | "design" : "com.android.support:design:$dependVersion.supportVersion",
39 | "recyclerview-v7" : "com.android.support:recyclerview-v7:$dependVersion.supportVersion",
40 | "constraint-layout" : "com.android.support.constraint:constraint-layout:$dependVersion.constraint_layout"
41 |
42 | ]
43 |
44 | test=[
45 | "junit" : "junit:junit:$dependVersion.junit",
46 | "runner" : "com.android.support.test:runner:$dependVersion.runner",
47 | "espresso-core" : "com.android.support.test.espresso:espresso-core:$dependVersion.espresso_core"
48 | ]
49 |
50 | rxJava = [
51 | "rxJava" : "io.reactivex.rxjava2:rxjava:$dependVersion.rxJava",
52 | "rxAndroid" : "io.reactivex.rxjava2:rxandroid:$dependVersion.rxAndroid"
53 | ]
54 |
55 | retrofit = [
56 | "retrofit" : "com.squareup.retrofit2:retrofit:$dependVersion.retrofit",
57 | "retrofit-gson" : "com.squareup.retrofit2:converter-gson:$dependVersion.retrofit",
58 | "retrofit-adapter" : "com.squareup.retrofit2:adapter-rxjava2:$dependVersion.retrofit"
59 | ]
60 |
61 | rxLifecycle =[
62 | "rxlifecycle" : "com.trello.rxlifecycle2:rxlifecycle:$dependVersion.rxlifecycle",
63 | "rxlifecycle-components" :"com.trello.rxlifecycle2:rxlifecycle-components:$dependVersion.rxlifecycle"
64 | ]
65 |
66 | okhttp = [
67 | "logging-interceptor" : "com.squareup.okhttp3:logging-interceptor:$dependVersion.logging_interceptor"
68 | ]
69 |
70 | arouter = [
71 | "arouter-api" : "com.alibaba:arouter-api:$dependVersion.arouter_api",
72 | "arouter-compiler" : "com.alibaba:arouter-compiler:$dependVersion.arouter_compiler"
73 | ]
74 |
75 | butterknife= [
76 | "butterknife" : "com.jakewharton:butterknife:$dependVersion.butterknife",
77 | "butterknife-compiler" : "com.jakewharton:butterknife-compiler:$dependVersion.butterknife"
78 | ]
79 |
80 | eventbus= [
81 | "eventbus" : "org.greenrobot:eventbus:$dependVersion.evenbus"
82 | ]
83 |
84 | bugly=[
85 | "bugly" : "com.tencent.bugly:crashreport_upgrade:1.3.6",
86 | // 指定tinker依赖版本(注:应用升级1.3.5版本起,不再内置tinker)
87 | "thinker" : "com.tencent.tinker:tinker-android-lib:1.9.14",
88 | "bugly-report" : "com.tencent.bugly:nativecrashreport:3.1.0" //其中latest.release指代最新版本号,也可以指定明确的版本号,例如2.2.0
89 | ]
90 |
91 | multidex=[
92 | "multidex" : "com.android.support:multidex:$dependVersion.multidex" // 多dex配置
93 | ]
94 |
95 | walle =[
96 | "walle" : "com.meituan.android.walle:library:$dependVersion.walle"
97 | ]
98 |
99 | stetho=[
100 | "stetho" : "com.facebook.stetho:stetho:$dependVersion.stetho",
101 | "stetho-okhttp3" : "com.facebook.stetho:stetho-okhttp3:$dependVersion.stetho"
102 | ]
103 |
104 | rxpermissions=[
105 | "rxpermissions" : "com.github.tbruyelle:rxpermissions:$dependVersion.rxpermissions"
106 | ]
107 |
108 |
109 | }
110 |
--------------------------------------------------------------------------------
/login_module/src/main/res/layout/activity_ip_save.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
19 |
20 |
27 |
28 |
43 |
44 |
50 |
51 |
67 |
68 |
74 |
75 |
84 |
85 |
97 |
98 |
103 |
104 |
110 |
111 |
117 |
118 |
--------------------------------------------------------------------------------
/base_module/src/main/java/com/hydinin/base_module/api/RestPool.java:
--------------------------------------------------------------------------------
1 | package com.hydinin.base_module.api;
2 |
3 | import com.facebook.stetho.okhttp3.StethoInterceptor;
4 | import com.google.gson.Gson;
5 | import com.google.gson.GsonBuilder;
6 | import com.hydinin.base_module.BaseApplication;
7 | import com.hydinin.base_module.constant.Constant;
8 | import com.hydinin.base_module.utils.SPUtil;
9 |
10 | import java.io.File;
11 | import java.util.HashMap;
12 | import java.util.Set;
13 | import java.util.concurrent.TimeUnit;
14 |
15 | import okhttp3.Cache;
16 | import okhttp3.MediaType;
17 | import okhttp3.MultipartBody;
18 | import okhttp3.OkHttpClient;
19 | import okhttp3.RequestBody;
20 | import okhttp3.logging.HttpLoggingInterceptor;
21 | import retrofit2.Retrofit;
22 | import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
23 | import retrofit2.converter.gson.GsonConverterFactory;
24 |
25 | /**
26 | * Created by Android Studio
27 | * Project:ZhiChuang
28 | * Author:httvc
29 | * Email:jfjie2013@163.com
30 | * Date:2017/5/5.
31 | * 接口解析封装类
32 | */
33 |
34 | public class RestPool {
35 | private volatile static RestPool restPool;
36 | private Retrofit retrofit;
37 |
38 | private RestPool() {
39 | String ip = (String) SPUtil.get(BaseApplication.getInstance().getApplicationContext(), Constant.IpInfo.IP, "");
40 | String port = (String) SPUtil.get(BaseApplication.getInstance().getApplicationContext(), Constant.IpInfo.PORT, "");
41 | String url="http://"+ip+":"+port+"/portal/";
42 | HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
43 | // log拦截器 打印所有的log
44 | logging.setLevel(HttpLoggingInterceptor.Level.BODY);
45 | File cacheFile = new File(BaseApplication.getInstance().getCacheDir(), "cache");
46 | Cache cache = new Cache(cacheFile, 1024 * 1024 * 100);//100M
47 | OkHttpClient client = new OkHttpClient.Builder()
48 | .readTimeout(40, TimeUnit.SECONDS)
49 | .connectTimeout(5, TimeUnit.SECONDS).writeTimeout(5, TimeUnit.SECONDS) //设置超时
50 | .addInterceptor(logging)
51 | .addInterceptor(new HttpHeaderInterceptor())
52 | .addNetworkInterceptor(new HttpCacheInterceptor())
53 | .addNetworkInterceptor(new StethoInterceptor())
54 | // .sslSocketFactory(SslContextFactory.getSSLSocketFactoryForTwoWay()) https认证 如果要使用https且为自定义证书 可以去掉这两行注释,并自行配制证书。
55 | // .hostnameVerifier(new SafeHostnameVerifier())
56 | .cache(cache)
57 | .build();
58 |
59 | Gson gson = new GsonBuilder()
60 | .setDateFormat("yyyy-MM-dd'T'HH:mm:ssZ")
61 | .create();
62 | retrofit = new Retrofit.Builder()///192.168.1.219:8080
63 | .client(client)//"http://"+ip+":"+port+"/portal/
64 | .baseUrl(url)//192.168.1.186:8080
65 | .addConverterFactory(GsonConverterFactory.create(gson))
66 | .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
67 | .build();
68 |
69 | }
70 |
71 | public static RestPool getInstance() {
72 | if (restPool == null) {
73 | synchronized (RestPool.class) {
74 | if (restPool == null) {
75 | restPool = new RestPool();
76 | }
77 | }
78 | }
79 | return restPool;
80 | }
81 |
82 | public ApiService getApiService() {
83 | return retrofit.create(ApiService.class);
84 | }
85 |
86 | /**
87 | * 文件上传body
88 | *
89 | * @param key
90 | * @param mediaType
91 | * @param file
92 | * @return
93 | */
94 | public static MultipartBody.Part getMultiPart(String key, String mediaType, File file) {
95 | MultipartBody.Part body = MultipartBody.Part.createFormData(key, file.getName(),
96 | RequestBody.create(MediaType.parse(mediaType), file));
97 | return body;
98 | }
99 |
100 | public static RequestBody getRequestBody(String value) {
101 | return RequestBody.create(MediaType.parse("multipart/form-data"), value);
102 | }
103 |
104 | public static MultipartBody.Builder getMultiBuilder(HashMap map) {
105 | MultipartBody.Builder builder = new MultipartBody.Builder();
106 | builder.setType(MultipartBody.FORM);
107 | Set set = map.keySet();
108 | for (String key : set) {
109 | RequestBody requestFile =
110 | RequestBody.create(MediaType.parse("multipart/form-data"), map.get(key));
111 | builder.addFormDataPart(key, map.get(key).getName(), requestFile);
112 | }
113 | return builder;
114 | }
115 |
116 | /* private class SafeHostnameVerifier implements HostnameVerifier {
117 | @Override
118 | public boolean verify(String hostname, SSLSession session) {
119 | if (Constants.IP.equals(hostname)) {//校验hostname是否正确,如果正确则建立连接
120 | return true;
121 | }
122 | return false;
123 | }
124 | }*/
125 | }
126 |
--------------------------------------------------------------------------------
/app/src/main/java/com/hydinin/mesproject/MyApplication.java:
--------------------------------------------------------------------------------
1 | package com.hydinin.mesproject;
2 |
3 | import android.annotation.TargetApi;
4 | import android.content.Context;
5 | import android.os.StrictMode;
6 | import android.support.multidex.MultiDex;
7 | import android.util.Log;
8 | import android.widget.Toast;
9 |
10 | import com.hydinin.base_module.BaseApplication;
11 | import com.meituan.android.walle.WalleChannelReader;
12 | import com.tencent.bugly.Bugly;
13 | import com.tencent.bugly.beta.Beta;
14 | import com.tencent.bugly.beta.interfaces.BetaPatchListener;
15 | import com.tencent.bugly.beta.upgrade.UpgradeStateListener;
16 |
17 | import java.util.Locale;
18 |
19 |
20 | public class MyApplication extends BaseApplication {
21 | @Override
22 | public void onCreate() {
23 | super.onCreate();
24 |
25 | setStrictMode();
26 | // 设置是否开启热更新能力,默认为true
27 | Beta.enableHotfix = true;
28 | // 设置是否自动下载补丁
29 | Beta.canAutoDownloadPatch = true;
30 | // 设置是否提示用户重启
31 | Beta.canNotifyUserRestart = true;
32 | // 设置是否自动合成补丁
33 | Beta.canAutoPatch = true;
34 |
35 | /**
36 | * 全量升级状态回调
37 | */
38 | Beta.upgradeStateListener = new UpgradeStateListener() {
39 | @Override
40 | public void onUpgradeFailed(boolean b) {
41 |
42 | }
43 |
44 | @Override
45 | public void onUpgradeSuccess(boolean b) {
46 |
47 | }
48 |
49 | @Override
50 | public void onUpgradeNoVersion(boolean b) {
51 | Toast.makeText(getApplicationContext(), "最新版本", Toast.LENGTH_SHORT).show();
52 | }
53 |
54 | @Override
55 | public void onUpgrading(boolean b) {
56 | Toast.makeText(getApplicationContext(), "onUpgrading", Toast.LENGTH_SHORT).show();
57 | }
58 |
59 | @Override
60 | public void onDownloadCompleted(boolean b) {
61 |
62 | }
63 | };
64 |
65 | /**
66 | * 补丁回调接口,可以监听补丁接收、下载、合成的回调
67 | */
68 | Beta.betaPatchListener = new BetaPatchListener() {
69 | @Override
70 | public void onPatchReceived(String patchFileUrl) {
71 | Toast.makeText(getApplicationContext(), patchFileUrl, Toast.LENGTH_SHORT).show();
72 | }
73 |
74 | @Override
75 | public void onDownloadReceived(long savedLength, long totalLength) {
76 | Toast.makeText(getApplicationContext(), String.format(Locale.getDefault(),
77 | "%s %d%%",
78 | Beta.strNotificationDownloading,
79 | (int) (totalLength == 0 ? 0 : savedLength * 100 / totalLength)), Toast.LENGTH_SHORT).show();
80 | }
81 |
82 | @Override
83 | public void onDownloadSuccess(String patchFilePath) {
84 | Toast.makeText(getApplicationContext(), patchFilePath, Toast.LENGTH_SHORT).show();
85 | // Beta.applyDownloadedPatch();
86 | }
87 |
88 | @Override
89 | public void onDownloadFailure(String msg) {
90 | Toast.makeText(getApplicationContext(), msg, Toast.LENGTH_SHORT).show();
91 | }
92 |
93 | @Override
94 | public void onApplySuccess(String msg) {
95 | Toast.makeText(getApplicationContext(), msg, Toast.LENGTH_SHORT).show();
96 | }
97 |
98 | @Override
99 | public void onApplyFailure(String msg) {
100 | Toast.makeText(getApplicationContext(), msg, Toast.LENGTH_SHORT).show();
101 | }
102 |
103 | @Override
104 | public void onPatchRollback() {
105 | Toast.makeText(getApplicationContext(), "onPatchRollback", Toast.LENGTH_SHORT).show();
106 | }
107 | };
108 |
109 | long start = System.currentTimeMillis();
110 | Bugly.setUserId(this, "falue");
111 | Bugly.setUserTag(this, 123456);
112 | Bugly.putUserData(this, "key1", "123");
113 |
114 | String channel = WalleChannelReader.getChannel(getApplicationContext());
115 | Bugly.setAppChannel(getApplicationContext(), channel);
116 |
117 | // 这里实现SDK初始化,appId替换成你的在Bugly平台申请的appId,调试时将第三个参数设置为true
118 | Bugly.init(this, "43bf2e25dc", true);
119 | long end = System.currentTimeMillis();
120 | Log.e("init time--->", end - start + "ms");
121 | }
122 |
123 |
124 | @TargetApi(9)
125 | protected void setStrictMode() {
126 | StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder().permitAll().build());
127 | StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder().detectAll().penaltyLog().build());
128 | }
129 |
130 | @Override
131 | protected void attachBaseContext(Context base) {
132 | super.attachBaseContext(base);
133 | // you must install multiDex whatever tinker is installed!
134 | MultiDex.install(base);
135 | // 安装tinker
136 | Beta.installTinker();
137 | }
138 | }
139 |
--------------------------------------------------------------------------------
/login_module/src/main/res/layout/activity_login.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
19 |
20 |
27 |
28 |
44 |
45 |
51 |
52 |
69 |
70 |
76 |
77 |
89 |
90 |
102 |
103 |
107 |
108 |
114 |
115 |
122 |
123 |
--------------------------------------------------------------------------------
/base_module/src/main/java/com/hydinin/base_module/utils/SPUtil.java:
--------------------------------------------------------------------------------
1 | package com.hydinin.base_module.utils;
2 |
3 |
4 | import android.content.Context;
5 | import android.content.SharedPreferences;
6 |
7 | import java.lang.reflect.InvocationTargetException;
8 | import java.lang.reflect.Method;
9 | import java.util.Map;
10 |
11 | public class SPUtil {
12 |
13 | /**
14 | * SharedPreferences存储在sd卡中的文件名字
15 | */
16 | private static String getSpName(Context context) {
17 | return context.getPackageName() + "_preferences";
18 | }
19 |
20 | /**
21 | * 保存数据的方法,我们需要拿到保存数据的具体类型,然后根据类型调用不同的保存方法
22 | */
23 | public static void putAndApply(Context context, String key, Object o) {
24 |
25 | SharedPreferences sp = context.getSharedPreferences(getSpName(context), Context.MODE_PRIVATE);
26 | SharedPreferences.Editor editor = sp.edit();
27 |
28 | if (o instanceof String) {
29 | editor.putString(key, (String) o);
30 | } else if (o instanceof Integer) {
31 | editor.putInt(key, (Integer) o);
32 | } else if (o instanceof Float) {
33 | editor.putFloat(key, (Float) o);
34 | } else if (o instanceof Long) {
35 | editor.putLong(key, (Long) o);
36 | } else if (o instanceof Boolean) {
37 | editor.putBoolean(key, (Boolean) o);
38 | } else {
39 | editor.putString(key, o.toString());
40 | }
41 | //提交
42 | SharedPreferencesCompat.apply(editor);
43 | }
44 |
45 |
46 |
47 |
48 |
49 | /**
50 | * 得到保存数据的方法,我们根据默认值得到保存的数据的具体类型,然后调用相对于的方法获取值
51 | */
52 | public static Object get(Context context, String key, Object defaultObject) {
53 | SharedPreferences sp = context.getSharedPreferences(getSpName(context), Context.MODE_PRIVATE);
54 |
55 | if (defaultObject instanceof String) {
56 | return sp.getString(key, (String) defaultObject);
57 | } else if (defaultObject instanceof Integer) {
58 | return sp.getInt(key, (Integer) defaultObject);
59 | } else if (defaultObject instanceof Boolean) {
60 | return sp.getBoolean(key, (Boolean) defaultObject);
61 | } else if (defaultObject instanceof Float) {
62 | return sp.getFloat(key, (Float) defaultObject);
63 | } else if (defaultObject instanceof Long) {
64 | return sp.getLong(key, (Long) defaultObject);
65 | } else {
66 | return null;
67 | }
68 | }
69 |
70 | /**
71 | * 移除某个key值已经对应的值
72 | */
73 | public static void remove(Context context, String key) {
74 | SharedPreferences sp = context.getSharedPreferences(getSpName(context), Context.MODE_PRIVATE);
75 | SharedPreferences.Editor editor = sp.edit();
76 | editor.remove(key);
77 | SharedPreferencesCompat.apply(editor);
78 | }
79 |
80 | /**
81 | * 清除所有数据
82 | */
83 | public static void clear(Context context) {
84 | SharedPreferences sp = context.getSharedPreferences(getSpName(context), Context.MODE_PRIVATE);
85 | SharedPreferences.Editor editor = sp.edit();
86 | editor.clear();
87 | SharedPreferencesCompat.apply(editor);
88 | }
89 |
90 | /**
91 | * 查询某个key是否已经存在
92 | */
93 | public static boolean contains(Context context, String key) {
94 | SharedPreferences sp = context.getSharedPreferences(getSpName(context), Context.MODE_PRIVATE);
95 | return sp.contains(key);
96 | }
97 |
98 | /**
99 | * 返回所有的键值对
100 | */
101 | public static Map getAll(Context context) {
102 | SharedPreferences sp = context.getSharedPreferences(getSpName(context), Context.MODE_PRIVATE);
103 | return sp.getAll();
104 | }
105 |
106 | //*************************************内部类*******************************************//
107 |
108 | /**
109 | * 优先使用SharedPreferences的apply方法,如果找不到则使用commit方法
110 | */
111 | private static class SharedPreferencesCompat {
112 |
113 | //查看SharedPreferences是否有apply方法
114 | private static final Method sApplyMethod = findApply();
115 |
116 | /**
117 | * 反射查找apply的方法
118 | *
119 | * @return
120 | */
121 | @SuppressWarnings({ "unchecked", "rawtypes" })
122 | private static Method findApply() {
123 |
124 | try {
125 | Class cls = SharedPreferences.Editor.class;
126 | return cls.getMethod("apply");
127 | } catch (NoSuchMethodException e) {
128 | e.printStackTrace();
129 | }
130 | return null;
131 | }
132 |
133 | /**
134 | * 如果找到则使用apply执行,否则使用commit
135 | */
136 | public static void apply(SharedPreferences.Editor editor) {
137 |
138 | try {
139 | if (sApplyMethod != null) {
140 | sApplyMethod.invoke(editor);
141 | return;
142 | }
143 | } catch (IllegalAccessException e) {
144 | e.printStackTrace();
145 | } catch (InvocationTargetException e) {
146 | e.printStackTrace();
147 | }
148 |
149 | editor.commit();
150 | }
151 |
152 | }
153 |
154 | }
--------------------------------------------------------------------------------
/base_module/src/main/res/layout/layout_head.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
13 |
14 |
22 |
23 |
36 |
37 |
38 |
49 |
50 |
61 |
62 |
63 |
71 |
72 |
73 |
74 |
75 |
80 |
81 |
82 |
89 |
90 |
91 |
92 |
97 |
98 |
111 |
112 |
113 |
114 |
115 |
116 |
128 |
129 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Attempt to set APP_HOME
10 | # Resolve links: $0 may be a link
11 | PRG="$0"
12 | # Need this for relative symlinks.
13 | while [ -h "$PRG" ] ; do
14 | ls=`ls -ld "$PRG"`
15 | link=`expr "$ls" : '.*-> \(.*\)$'`
16 | if expr "$link" : '/.*' > /dev/null; then
17 | PRG="$link"
18 | else
19 | PRG=`dirname "$PRG"`"/$link"
20 | fi
21 | done
22 | SAVED="`pwd`"
23 | cd "`dirname \"$PRG\"`/" >/dev/null
24 | APP_HOME="`pwd -P`"
25 | cd "$SAVED" >/dev/null
26 |
27 | APP_NAME="Gradle"
28 | APP_BASE_NAME=`basename "$0"`
29 |
30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
31 | DEFAULT_JVM_OPTS=""
32 |
33 | # Use the maximum available, or set MAX_FD != -1 to use that value.
34 | MAX_FD="maximum"
35 |
36 | warn () {
37 | echo "$*"
38 | }
39 |
40 | die () {
41 | echo
42 | echo "$*"
43 | echo
44 | exit 1
45 | }
46 |
47 | # OS specific support (must be 'true' or 'false').
48 | cygwin=false
49 | msys=false
50 | darwin=false
51 | nonstop=false
52 | case "`uname`" in
53 | CYGWIN* )
54 | cygwin=true
55 | ;;
56 | Darwin* )
57 | darwin=true
58 | ;;
59 | MINGW* )
60 | msys=true
61 | ;;
62 | NONSTOP* )
63 | nonstop=true
64 | ;;
65 | esac
66 |
67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
68 |
69 | # Determine the Java command to use to start the JVM.
70 | if [ -n "$JAVA_HOME" ] ; then
71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
72 | # IBM's JDK on AIX uses strange locations for the executables
73 | JAVACMD="$JAVA_HOME/jre/sh/java"
74 | else
75 | JAVACMD="$JAVA_HOME/bin/java"
76 | fi
77 | if [ ! -x "$JAVACMD" ] ; then
78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
79 |
80 | Please set the JAVA_HOME variable in your environment to match the
81 | location of your Java installation."
82 | fi
83 | else
84 | JAVACMD="java"
85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
86 |
87 | Please set the JAVA_HOME variable in your environment to match the
88 | location of your Java installation."
89 | fi
90 |
91 | # Increase the maximum file descriptors if we can.
92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
93 | MAX_FD_LIMIT=`ulimit -H -n`
94 | if [ $? -eq 0 ] ; then
95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
96 | MAX_FD="$MAX_FD_LIMIT"
97 | fi
98 | ulimit -n $MAX_FD
99 | if [ $? -ne 0 ] ; then
100 | warn "Could not set maximum file descriptor limit: $MAX_FD"
101 | fi
102 | else
103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
104 | fi
105 | fi
106 |
107 | # For Darwin, add options to specify how the application appears in the dock
108 | if $darwin; then
109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
110 | fi
111 |
112 | # For Cygwin, switch paths to Windows format before running java
113 | if $cygwin ; then
114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
116 | JAVACMD=`cygpath --unix "$JAVACMD"`
117 |
118 | # We build the pattern for arguments to be converted via cygpath
119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
120 | SEP=""
121 | for dir in $ROOTDIRSRAW ; do
122 | ROOTDIRS="$ROOTDIRS$SEP$dir"
123 | SEP="|"
124 | done
125 | OURCYGPATTERN="(^($ROOTDIRS))"
126 | # Add a user-defined pattern to the cygpath arguments
127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
129 | fi
130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
131 | i=0
132 | for arg in "$@" ; do
133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
135 |
136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
138 | else
139 | eval `echo args$i`="\"$arg\""
140 | fi
141 | i=$((i+1))
142 | done
143 | case $i in
144 | (0) set -- ;;
145 | (1) set -- "$args0" ;;
146 | (2) set -- "$args0" "$args1" ;;
147 | (3) set -- "$args0" "$args1" "$args2" ;;
148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
154 | esac
155 | fi
156 |
157 | # Escape application args
158 | save () {
159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
160 | echo " "
161 | }
162 | APP_ARGS=$(save "$@")
163 |
164 | # Collect all arguments for the java command, following the shell quoting and substitution rules
165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
166 |
167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
169 | cd "$(dirname "$0")"
170 | fi
171 |
172 | exec "$JAVACMD" "$@"
173 |
--------------------------------------------------------------------------------
/login_module/src/main/java/com/hydinin/login_module/LoginActivity.java:
--------------------------------------------------------------------------------
1 | package com.hydinin.login_module;
2 |
3 | import android.content.Intent;
4 | import android.os.Bundle;
5 | import android.util.Log;
6 | import android.view.View;
7 | import android.widget.CheckBox;
8 | import android.widget.EditText;
9 | import android.widget.Toast;
10 |
11 | import com.alibaba.android.arouter.facade.annotation.Route;
12 | import com.hydinin.base_module.api.HttpResult;
13 | import com.hydinin.base_module.arouter.ARouteConstant;
14 | import com.hydinin.base_module.base.MVPActivity;
15 | import com.hydinin.base_module.beanJson.User;
16 | import com.hydinin.base_module.constant.Constant;
17 | import com.hydinin.base_module.utils.CommonUtils;
18 | import com.hydinin.base_module.utils.SPUtil;
19 | import com.hydinin.base_module.utils.ToastUtil;
20 | import com.hydinin.base_module.utils.UIHelper;
21 |
22 | import butterknife.BindView;
23 | import butterknife.OnClick;
24 |
25 |
26 | @Route(path = ARouteConstant.Login_Activity_login)
27 | public class LoginActivity extends MVPActivity implements LoginContract.LoginView {
28 |
29 |
30 | @BindView(R2.id.login_user)
31 | EditText loginUser;
32 | @BindView(R2.id.login_pwd)
33 | EditText loginPwd;
34 | @BindView(R2.id.login_record)
35 | CheckBox loginRecord;
36 | private String userName;
37 | private String pwd;
38 |
39 | private long mLastClickTime = 0;
40 | public static final long TIME_INTERVAL = 1000L;
41 |
42 | @Override
43 | protected void onCreate(Bundle savedInstanceState) {
44 | super.onCreate(savedInstanceState);
45 | Log.i("sssssLoginActivity","onCreate");
46 | }
47 |
48 | @Override
49 | public void initView() {
50 | Boolean isRecord = (Boolean) SPUtil.get(this, Constant.ISRECORD, false);
51 | String name = (String) SPUtil.get(this, Constant.LoginInfo.LOGINNAME, "");
52 | String pwd = (String) SPUtil.get(this, Constant.LoginInfo.LOGINPWD, "");
53 | if (isRecord){
54 | loginUser.setText(name);
55 | loginPwd.setText(pwd);
56 | loginRecord.setChecked(true);
57 | }else {
58 | loginUser.setText(name);
59 | loginRecord.setChecked(false);
60 | }
61 | String ip = (String) SPUtil.get(this, Constant.IpInfo.IP, "");
62 | String port = (String) SPUtil.get(this, Constant.IpInfo.PORT, "");
63 | if (!CommonUtils.isEmpty(ip) && !CommonUtils.isEmpty(port)) {
64 | //getVersion();
65 | } else {
66 | SPUtil.putAndApply(this, Constant.IpInfo.IP, Constant.SERVERIP);
67 | SPUtil.putAndApply(this, Constant.IpInfo.PORT, Constant.SERVERPORT);
68 | }
69 | }
70 |
71 | @OnClick({R2.id.login_login,R2.id.login_ip})
72 | void setOnClick(View view){
73 | int id = view.getId();
74 | if (id==R.id.login_login){
75 | userName = loginUser.getText().toString().trim();
76 | pwd = loginPwd.getText().toString().trim();
77 | String ip = (String) SPUtil.get(this, Constant.IpInfo.IP, "");
78 | String port = (String) SPUtil.get(this, Constant.IpInfo.PORT, "");
79 | if (!CommonUtils.isEmpty(ip) && !CommonUtils.isEmpty(port)) {
80 | if (!CommonUtils.isEmpty(userName) && !CommonUtils.isEmpty(pwd)) {
81 | mPresenter.loginUser(this,userName, pwd,this.>bindToLifecycle());
82 | } else {
83 | Toast.makeText(this, "用户名密码不能为空", Toast.LENGTH_SHORT).show();
84 | }
85 | } else {
86 | Toast.makeText(this, "请去ip页面输入ip和端口", Toast.LENGTH_SHORT).show();
87 | }
88 | }else if (id==R.id.login_ip){
89 | long nowTime = System.currentTimeMillis();
90 | if (nowTime - mLastClickTime > TIME_INTERVAL) {
91 | UIHelper.openActivity(this,IpSaveActivity.class);
92 | mLastClickTime = nowTime;
93 | } else {
94 | //Toast.makeText(LoginActivity.this, "不要重复点击", Toast.LENGTH_SHORT).show();
95 | }
96 | }
97 | }
98 |
99 | @Override
100 | protected void onRestart() {
101 | super.onRestart();
102 | Log.i("sssssLoginActivity","onRestart");
103 | }
104 |
105 | @Override
106 | protected void onStart() {
107 | super.onStart();
108 | Log.i("sssssLoginActivity","onStart");
109 | }
110 |
111 | @Override
112 | protected void onResume() {
113 | super.onResume();
114 | Log.i("sssssLoginActivity","onResume");
115 | }
116 |
117 | @Override
118 | protected void onPause() {
119 | super.onPause();
120 | Log.i("sssssLoginActivity","onPause");
121 | }
122 |
123 | @Override
124 | protected void onStop() {
125 | super.onStop();
126 | Log.i("sssssLoginActivity","onStop");
127 | }
128 |
129 | @Override
130 | protected void onDestroy() {
131 | super.onDestroy();
132 | Log.i("sssssLoginActivity","onDestroy");
133 | }
134 |
135 | @Override
136 | public int getLayout() {
137 | return R.layout.activity_login;
138 | }
139 |
140 | @Override
141 | public void showUserDate(User user) {
142 | SPUtil.putAndApply(LoginActivity.this,Constant.ISRECORD,loginRecord.isChecked());
143 | if (loginRecord.isChecked()){
144 | SPUtil.putAndApply(LoginActivity.this, Constant.LoginInfo.LOGINNAME,userName);
145 | SPUtil.putAndApply(LoginActivity.this, Constant.LoginInfo.LOGINPWD, pwd);
146 | }else {
147 | SPUtil.putAndApply(LoginActivity.this, Constant.LoginInfo.LOGINNAME,userName);
148 | }
149 | //SPUtil.putAndApply(this, Constant.USERID,user.getId()+"");
150 | // Intent intent = new Intent(LoginActivity.this, MainActivity.class);
151 | // intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
152 | // startActivity(intent);
153 | ARouteConstant.startMainActivity(user);
154 | this.finish();
155 | }
156 |
157 | @Override
158 | public void showError(String message) {
159 | ToastUtil.show(getApplicationContext(),message);
160 | User user=new User();
161 | ARouteConstant.startMainActivity(user);
162 | }
163 | }
164 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/base_module/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 |
--------------------------------------------------------------------------------