├── .gitignore ├── README.md ├── app ├── .gitignore ├── build.gradle ├── libs │ └── commons-codec-1.6.jar ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── bonait │ │ └── bnframework │ │ └── ExampleInstrumentedTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── assets │ │ └── litepal.xml │ ├── java │ │ └── com │ │ │ └── bonait │ │ │ └── bnframework │ │ │ ├── MainApplication.java │ │ │ ├── common │ │ │ ├── base │ │ │ │ ├── BaseActivity.java │ │ │ │ ├── BaseFragment.java │ │ │ │ └── BaseFragmentActivity.java │ │ │ ├── constant │ │ │ │ ├── Constants.java │ │ │ │ └── SPConstants.java │ │ │ ├── http │ │ │ │ ├── GsonConvert.java │ │ │ │ ├── callback │ │ │ │ │ ├── bitmap │ │ │ │ │ │ └── BitmapDialogCallback.java │ │ │ │ │ ├── files │ │ │ │ │ │ └── FileProgressDialogCallBack.java │ │ │ │ │ ├── files2 │ │ │ │ │ │ ├── FileCallback2.java │ │ │ │ │ │ ├── FileConvert2.java │ │ │ │ │ │ ├── FileProgressDialogCallBack2.java │ │ │ │ │ │ └── ReadMe.txt │ │ │ │ │ ├── json │ │ │ │ │ │ ├── JsonCallback.java │ │ │ │ │ │ ├── JsonConvert.java │ │ │ │ │ │ └── JsonDialogCallback.java │ │ │ │ │ └── strings │ │ │ │ │ │ └── StringDialogCallback.java │ │ │ │ └── exception │ │ │ │ │ └── TokenException.java │ │ │ ├── interfaces │ │ │ │ └── OnDoIntListener.java │ │ │ ├── model │ │ │ │ ├── BaseCodeJson.java │ │ │ │ ├── BaseJson.java │ │ │ │ ├── SimpleBaseJson.java │ │ │ │ └── SimpleCodeJson.java │ │ │ ├── notification │ │ │ │ ├── DownloadNotification.java │ │ │ │ └── MainNotification.java │ │ │ ├── utils │ │ │ │ ├── AlertDialogUtils.java │ │ │ │ ├── AnimationToolUtils.java │ │ │ │ ├── AppFileUtils.java │ │ │ │ ├── AppUtils.java │ │ │ │ ├── Des3Utils.java │ │ │ │ ├── FileUtils.java │ │ │ │ ├── KeyboardToolUtils.java │ │ │ │ ├── MediaFileUtils.java │ │ │ │ ├── NetworkUtils.java │ │ │ │ ├── PreferenceUtils.java │ │ │ │ ├── ToastUtils.java │ │ │ │ ├── UpdateAppUtils.java │ │ │ │ └── UriUtils.java │ │ │ └── view │ │ │ │ ├── ClearEditTextView.java │ │ │ │ └── QMAutoDialogBuilderView.java │ │ │ ├── manager │ │ │ └── ActivityLifecycleManager.java │ │ │ ├── modules │ │ │ ├── home │ │ │ │ ├── activity │ │ │ │ │ ├── BottomNavigation2Activity.java │ │ │ │ │ └── BottomNavigationActivity.java │ │ │ │ ├── adapter │ │ │ │ │ └── FragmentAdapter.java │ │ │ │ └── fragment │ │ │ │ │ ├── Home1Fragment.java │ │ │ │ │ ├── Home2Fragment.java │ │ │ │ │ └── Home3Fragment.java │ │ │ ├── mine │ │ │ │ ├── fragment │ │ │ │ │ └── MyFragment.java │ │ │ │ └── model │ │ │ │ │ └── UpdateAppPo.java │ │ │ └── welcome │ │ │ │ ├── activity │ │ │ │ ├── LoginActivity.java │ │ │ │ └── WelcomeActivity.java │ │ │ │ └── model │ │ │ │ └── AppLoginPo.java │ │ │ └── test │ │ │ ├── Test.java │ │ │ └── TestActivity.java │ └── res │ │ ├── color │ │ ├── s_app_color_blue_2.xml │ │ ├── s_app_color_gray.xml │ │ ├── s_btn_blue_bg.xml │ │ ├── s_btn_blue_border.xml │ │ ├── s_btn_blue_text.xml │ │ └── s_topbar_btn_color.xml │ │ ├── drawable-hdpi │ │ ├── icon_pass_gone.png │ │ ├── icon_pass_visuable.png │ │ ├── icon_personal_announcement.png │ │ ├── icon_personal_pwd.png │ │ ├── icon_personal_sex.png │ │ ├── icon_personal_sign.png │ │ ├── icon_personal_update.png │ │ └── icon_personal_user.png │ │ ├── drawable-v24 │ │ └── ic_launcher_foreground.xml │ │ ├── drawable-xhdpi │ │ ├── icon_login_pwd.png │ │ └── icon_login_user.png │ │ ├── drawable-xxhdpi │ │ ├── icon_delete_fill.png │ │ ├── icon_delete_fill_select.png │ │ ├── icon_personal_announcement.png │ │ ├── icon_personal_download_files.png │ │ ├── icon_personal_pwd.png │ │ ├── icon_personal_sex.png │ │ ├── icon_personal_sign.png │ │ ├── icon_personal_update.png │ │ ├── icon_personal_user.png │ │ ├── icon_right.png │ │ └── icon_user_pic.png │ │ ├── drawable │ │ ├── bg_btn_login_selected.xml │ │ ├── common_bg_with_radius_and_border.xml │ │ ├── delete_selector.xml │ │ ├── ic_dashboard_black_24dp.xml │ │ ├── ic_home_black_24dp.xml │ │ ├── ic_launcher_background.xml │ │ ├── ic_notifications_black_24dp.xml │ │ ├── icon_home1_selector.xml │ │ ├── icon_home2_selector.xml │ │ ├── icon_home_my_selector.xml │ │ ├── radius_button_bg.xml │ │ ├── radius_button_bg_pressed.xml │ │ ├── s_radius_button_bg.xml │ │ ├── tab_panel_bg.xml │ │ └── welcome.xml │ │ ├── layout │ │ ├── activity_bottom_navigation.xml │ │ ├── activity_bottom_navigation2.xml │ │ ├── activity_login.xml │ │ ├── activity_test.xml │ │ ├── activity_welcome.xml │ │ ├── fragment_home1.xml │ │ ├── fragment_home2.xml │ │ ├── fragment_home3.xml │ │ ├── fragment_my.xml │ │ └── toast_layout.xml │ │ ├── menu │ │ └── navigation.xml │ │ ├── mipmap-anydpi-v26 │ │ ├── ic_launcher.xml │ │ └── ic_launcher_round.xml │ │ ├── mipmap-hdpi │ │ ├── ic_check_white_48dp.png │ │ ├── ic_clear_white_48dp.png │ │ ├── ic_error_outline_white_48dp.png │ │ ├── ic_info_outline_white_48dp.png │ │ ├── ic_launcher.png │ │ ├── ic_launcher_round.png │ │ └── toast_frame.9.png │ │ ├── mipmap-mdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxhdpi │ │ ├── ic_launcher.png │ │ ├── ic_launcher_round.png │ │ ├── icon_tabbar_component.png │ │ ├── icon_tabbar_component_selected.png │ │ ├── icon_tabbar_lab.png │ │ ├── icon_tabbar_lab_selected.png │ │ ├── icon_tabbar_util.png │ │ └── icon_tabbar_util_selected.png │ │ ├── mipmap-xxxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── values │ │ ├── attr.xml │ │ ├── colors.xml │ │ ├── dimens.xml │ │ ├── ids.xml │ │ ├── strings.xml │ │ └── styles.xml │ │ └── xml │ │ ├── app_provider_paths.xml │ │ └── network_security_config.xml │ └── test │ └── java │ └── com │ └── bonait │ └── bnframework │ └── ExampleUnitTest.java ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── img_folder ├── im_login.png └── im_pager1.png └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/caches 5 | /.idea/libraries 6 | /.idea/modules.xml 7 | /.idea/workspace.xml 8 | /.idea/navEditor.xml 9 | /.idea/assetWizardSettings.xml 10 | .DS_Store 11 | /build 12 | /captures 13 | .externalNativeBuild 14 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | # Framework_Android 3 | Android架构搭建,根据腾讯QMUI_Android框架搭建,适用于快速运用到项目中去。 4 | 由于本项目与自己的后台服务器搭配使用,在使用时请改成自己的服务器IP地址。 5 | 6 | 感谢QMUI_Android团队为广大开发者提供的 UI 库 ,官网:[http://qmuiteam.com/android](http://qmuiteam.com/android) 7 | 8 | 9 | ### (随缘更新) 10 | 11 | ### 开发日志 —— 2 12 | - 添加并重写OkGo中的JsonCallback,添加JsonConvert类,对后台baseJson进行统一管理。 13 | 每个项目请求后台返回的json格式都有所不同,**请根据实际项目需求修改JsonConvert类**。 本项目同时提供了两种json格式进行解析操作: 14 | 1. json格式为`{code:0,msg:"成功",result:{…}}`。 15 | 根据后台返回的`code`数值来判断返回的数据是否成功。`code:0`表示成功返回,`code:101` 等其他标识表示返回失败,并返回失败的`msg`。 16 | 2. json格式为`{success:true,msg:"成功",result:{…}}`。 17 | 根据后台返回的`success`数值来判断返回的数据是否成功。`success:true`表示成功返回,`success:false` 表示返回失败,并返回失败的`msg`。 18 | 19 | - 实现启动和登录功能,在app启动时通过后台服务器判断token是否失效,如果没有token或者失效,则跳转到登录页面,反之直接跳转到主界面。 20 | - 添加测试用户信息开关,并且在gradle配置只能在debug版本使用,当编译成release正式版时,关闭测试用户信息开关。 21 | - 添加SPConstants,统一管理SharedPreferences的key。 22 | 23 | ### 开发日志 —— 1 24 | 25 | - 根据QMUI搭建viewPager+fragment+Navigation主页,添加Android7.0 provider 26 | - 添加登录界面,界面根据软键盘弹出自适应上下移动,添加文件相关工具类 27 | - 添加OkGo并配置框架,添加Logger框架,添加内存泄漏检测框架,base类添加EasyPermission权限管理框架。 28 | 29 | ### 项目截图(持续更新) 30 | ![登录界面](https://raw.githubusercontent.com/FadedYu/Framework_Android/master/img_folder/im_login.png) 31 | ![主页](https://raw.githubusercontent.com/FadedYu/Framework_Android/master/img_folder/im_pager1.png) 32 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion rootProject.ext.compileSdkVersion 5 | buildToolsVersion rootProject.ext.buildToolsVersion 6 | 7 | defaultConfig { 8 | applicationId "com.bonait.bnframework" 9 | minSdkVersion rootProject.ext.minSdkVersion 10 | targetSdkVersion rootProject.ext.targetSdkVersion 11 | versionCode rootProject.ext.versionCode 12 | versionName rootProject.ext.versionName 13 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 14 | } 15 | buildTypes { 16 | release { 17 | minifyEnabled false 18 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' 19 | 20 | resValue("bool","superAdminTest","false") 21 | } 22 | 23 | debug { 24 | resValue("string", "PORT_NUMBER", "8081") 25 | resValue("bool","superAdminTest","true") 26 | } 27 | } 28 | } 29 | 30 | dependencies { 31 | implementation fileTree(include: ['*.jar'], dir: 'libs') 32 | 33 | //测试相关 34 | testImplementation 'junit:junit:4.13-beta-2' 35 | androidTestImplementation 'com.android.support.test:runner:1.0.2' 36 | androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' 37 | implementation 'com.android.support.constraint:constraint-layout:1.1.3' 38 | 39 | //支持包 40 | implementation 'com.android.support:design:28.0.0' 41 | implementation 'com.android.support:appcompat-v7:28.0.0' 42 | implementation "com.android.support:recyclerview-v7:$rootProject.supportVersion" 43 | implementation "com.android.support:design:$rootProject.supportVersion" 44 | implementation "com.android.support:cardview-v7:$rootProject.supportVersion" 45 | implementation "com.android.support:support-vector-drawable:$rootProject.supportVersion" 46 | 47 | // QMUI框架 link: http://qmuiteam.com/android 48 | // 本App 搭建的基础框架,基本使用控件功能请看官网的功能列表 49 | implementation 'com.qmuiteam:qmui:1.2.0' 50 | implementation 'com.qmuiteam:arch:0.3.1' 51 | 52 | // RecyclerAdapter框架 53 | implementation 'com.github.CymChad:BaseRecyclerViewAdapterHelper:2.9.46' 54 | 55 | // OKGO网络协议封装框架 56 | implementation 'com.lzy.net:okgo:3.0.4' 57 | implementation 'com.google.code.gson:gson:2.8.0' 58 | 59 | // easyPermissions权限管理 60 | implementation 'pub.devrel:easypermissions:2.0.1' 61 | 62 | // butterKnife黄油刀 63 | implementation "com.jakewharton:butterknife:$rootProject.butterknife" 64 | annotationProcessor "com.jakewharton:butterknife-compiler:$rootProject.butterknife" 65 | 66 | // SuperTextView 67 | implementation 'com.github.lygttpod:SuperTextView:2.1.8' 68 | 69 | // android-saripaar 基于规则的Android表单验证库 70 | implementation 'com.mobsandgeeks:android-saripaar:2.0.3' 71 | 72 | // litePal 数据库操作框架 73 | implementation 'org.litepal.android:java:3.0.0' 74 | 75 | // SmartShow Toast框架,解决不同机型弹出方式缺陷问题 76 | implementation 'com.github.the-pig-of-jungle.smart-show:toast:2.6.7' 77 | 78 | // debug调试app本地数据库 79 | debugImplementation 'com.amitshekhar.android:debug-db:1.0.6' 80 | 81 | // log日志框架 82 | implementation 'com.orhanobut:logger:2.2.0' 83 | 84 | // leak 内存泄漏检测 85 | debugImplementation 'com.squareup.leakcanary:leakcanary-android:1.6.3' 86 | releaseImplementation 'com.squareup.leakcanary:leakcanary-android-no-op:1.6.3' 87 | // Optional, if you use support library fragments: 88 | debugImplementation 'com.squareup.leakcanary:leakcanary-support-fragment:1.6.3' 89 | implementation files('libs/commons-codec-1.6.jar') 90 | } 91 | -------------------------------------------------------------------------------- /app/libs/commons-codec-1.6.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YuiGod/Framework_Android/abc054cace5dcb439e5e5d065e50a2ce04cf6c8f/app/libs/commons-codec-1.6.jar -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /app/src/androidTest/java/com/bonait/bnframework/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package com.bonait.bnframework; 2 | 3 | import android.content.Context; 4 | import android.support.test.InstrumentationRegistry; 5 | import android.support.test.runner.AndroidJUnit4; 6 | 7 | import org.junit.Test; 8 | import org.junit.runner.RunWith; 9 | 10 | import static org.junit.Assert.*; 11 | 12 | /** 13 | * Instrumented test, which will execute on an Android device. 14 | * 15 | * @see Testing documentation 16 | */ 17 | @RunWith(AndroidJUnit4.class) 18 | public class ExampleInstrumentedTest { 19 | @Test 20 | public void useAppContext() { 21 | // Context of the app under test. 22 | Context appContext = InstrumentationRegistry.getTargetContext(); 23 | 24 | assertEquals("com.bonait.bnframework", appContext.getPackageName()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 28 | 33 | 36 | 37 | 38 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 60 | 61 | 62 | 63 | 64 | 65 | -------------------------------------------------------------------------------- /app/src/main/assets/litepal.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 11 | 12 | 13 | 22 | 23 | 24 | 34 | 35 | 36 | 37 | 38 | 48 | 49 | -------------------------------------------------------------------------------- /app/src/main/java/com/bonait/bnframework/MainApplication.java: -------------------------------------------------------------------------------- 1 | package com.bonait.bnframework; 2 | 3 | import android.annotation.SuppressLint; 4 | import android.app.Activity; 5 | import android.app.Application; 6 | import android.content.Context; 7 | 8 | import com.bonait.bnframework.manager.ActivityLifecycleManager; 9 | import com.bonait.bnframework.common.constant.Constants; 10 | import com.bonait.bnframework.common.notification.MainNotification; 11 | import com.bonait.bnframework.common.utils.AppUtils; 12 | import com.bonait.bnframework.common.utils.PreferenceUtils; 13 | import com.lzy.okgo.OkGo; 14 | import com.lzy.okgo.cache.CacheEntity; 15 | import com.lzy.okgo.cache.CacheMode; 16 | import com.lzy.okgo.interceptor.HttpLoggingInterceptor; 17 | import com.orhanobut.logger.AndroidLogAdapter; 18 | import com.orhanobut.logger.FormatStrategy; 19 | import com.orhanobut.logger.Logger; 20 | import com.orhanobut.logger.PrettyFormatStrategy; 21 | import com.qmuiteam.qmui.arch.QMUISwipeBackActivityManager; 22 | import com.squareup.leakcanary.LeakCanary; 23 | 24 | import org.litepal.LitePal; 25 | 26 | import java.util.concurrent.TimeUnit; 27 | import java.util.logging.Level; 28 | 29 | import okhttp3.OkHttpClient; 30 | 31 | /** 32 | * Created by LY on 2019/3/19. 33 | */ 34 | public class MainApplication extends Application { 35 | 36 | @SuppressLint("StaticFieldLeak") 37 | private static Context context; 38 | 39 | public static Context getContext() { 40 | return context; 41 | } 42 | 43 | @Override 44 | public void onCreate() { 45 | super.onCreate(); 46 | context = getApplicationContext(); 47 | 48 | // activity生命周期管理 49 | ActivityLifecycleManager.get().init(this); 50 | 51 | // QMUI 框架初始化 52 | QMUISwipeBackActivityManager.init(this); 53 | 54 | // LitePal 数据库初始化 55 | LitePal.initialize(this); 56 | 57 | // 全局配置OkGo 58 | initOkGo(); 59 | 60 | // 配置sharedPreferences 61 | PreferenceUtils.initPreference(this, AppUtils.getAppName(this), Activity.MODE_PRIVATE); 62 | 63 | // 初始化通知栏消息渠道 64 | MainNotification.initNotificationChannel(this); 65 | 66 | // 内存泄漏检测 67 | initLeakCanary(false); 68 | 69 | // Log日志打印框架 70 | initLogCat(); 71 | 72 | // SmartShow Toast框架,暂时不用,先使用ToastUtils工具类的 73 | //SmartShow.init(this); 74 | } 75 | 76 | //========================================================================// 77 | 78 | /** 79 | * 内存泄漏检测,根据flag来判断要不要初始化 80 | */ 81 | private void initLeakCanary(boolean flag) { 82 | if (flag) { 83 | // leak 内存检测注册 84 | if (LeakCanary.isInAnalyzerProcess(this)) { 85 | return; 86 | } 87 | LeakCanary.install(this); 88 | } 89 | } 90 | 91 | /** 92 | * 初始化log日志框架 93 | */ 94 | private void initLogCat() { 95 | FormatStrategy formatStrategy = PrettyFormatStrategy.newBuilder() 96 | .showThreadInfo(false) // (可选)是否显示线程信息。 默认值为true 97 | .methodCount(2) // (可选)要显示的方法行数。 默认2 98 | .build(); 99 | Logger.addLogAdapter(new AndroidLogAdapter(formatStrategy) { 100 | @Override 101 | public boolean isLoggable(int priority, String tag) { 102 | return BuildConfig.DEBUG; 103 | } 104 | }); 105 | } 106 | 107 | /** 108 | * 配置OkGo 109 | */ 110 | private void initOkGo() { 111 | 112 | //---------这里给出的是示例代码,告诉你可以这么传,实际使用的时候,根据需要传,不需要就不传-------------// 113 | /*HttpHeaders headers = new HttpHeaders(); 114 | headers.put("commonHeaderKey1", "commonHeaderValue1"); //header不支持中文,不允许有特殊字符 115 | headers.put("commonHeaderKey2", "commonHeaderValue2"); 116 | HttpParams params = new HttpParams(); 117 | params.put("commonParamsKey1", "commonParamsValue1"); //param支持中文,直接传,不要自己编码 118 | params.put("commonParamsKey2", "这里支持中文参数");*/ 119 | //----------------------------------------------------------------------------------------// 120 | 121 | OkHttpClient.Builder builder = new OkHttpClient.Builder(); 122 | 123 | //log相关 124 | HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor("OkGo"); 125 | //log打印级别,决定了log显示的详细程度 126 | loggingInterceptor.setPrintLevel(HttpLoggingInterceptor.Level.BODY); 127 | //log颜色级别,决定了log在控制台显示的颜色 128 | loggingInterceptor.setColorLevel(Level.INFO); 129 | //添加OkGo默认debug日志 130 | builder.addInterceptor(loggingInterceptor); 131 | 132 | //-------------------------配置超时时间,默认60000ms,60s------------------------------// 133 | //OkGo.DEFAULT_MILLISECONDS 134 | //全局的连接超时时间 135 | builder.connectTimeout(Constants.CONNECT_TIME_OUT, TimeUnit.MILLISECONDS); 136 | //全局的读取超时时间 137 | builder.readTimeout(Constants.CONNECT_TIME_OUT, TimeUnit.MILLISECONDS); 138 | //全局的写入超时时间 139 | builder.writeTimeout(OkGo.DEFAULT_MILLISECONDS, TimeUnit.MILLISECONDS); 140 | 141 | OkGo.getInstance().init(this) //必须调用初始化 142 | .setOkHttpClient(builder.build()) //建议设置OkHttpClient,不设置将使用默认的 143 | .setCacheMode(CacheMode.NO_CACHE) //全局统一缓存模式,默认不使用缓存,可以不传 144 | .setCacheTime(CacheEntity.CACHE_NEVER_EXPIRE) //全局统一缓存时间,默认永不过期,可以不传 145 | .setRetryCount(3); //全局统一超时重连次数,默认为三次,那么最差的情况会请求4次(一次原始请求,三次重连请求),不需要可以设置为0 146 | //.addCommonParams(params); //全局公共参数 147 | 148 | } 149 | 150 | 151 | } 152 | -------------------------------------------------------------------------------- /app/src/main/java/com/bonait/bnframework/common/base/BaseActivity.java: -------------------------------------------------------------------------------- 1 | package com.bonait.bnframework.common.base; 2 | 3 | import android.annotation.SuppressLint; 4 | import android.content.Intent; 5 | import android.net.Uri; 6 | import android.provider.Settings; 7 | import android.support.annotation.NonNull; 8 | import android.support.annotation.Nullable; 9 | 10 | import com.bonait.bnframework.MainApplication; 11 | import com.bonait.bnframework.common.constant.Constants; 12 | import com.bonait.bnframework.common.utils.AlertDialogUtils; 13 | import com.bonait.bnframework.common.utils.ToastUtils; 14 | import com.qmuiteam.qmui.arch.QMUIActivity; 15 | import com.qmuiteam.qmui.util.QMUIDisplayHelper; 16 | import com.qmuiteam.qmui.widget.dialog.QMUIDialog; 17 | import com.qmuiteam.qmui.widget.dialog.QMUIDialogAction; 18 | 19 | import java.util.List; 20 | 21 | import pub.devrel.easypermissions.EasyPermissions; 22 | 23 | 24 | /** 25 | * Created by LY on 2019/3/21. 26 | */ 27 | @SuppressLint("Registered") 28 | public class BaseActivity extends QMUIActivity implements EasyPermissions.PermissionCallbacks { 29 | 30 | @Override 31 | protected int backViewInitOffset() { 32 | return QMUIDisplayHelper.dp2px(MainApplication.getContext(), 100); 33 | } 34 | 35 | @Override 36 | protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { 37 | super.onActivityResult(requestCode, resultCode, data); 38 | 39 | if (requestCode == Constants.APP_SETTING_DIALOG_REQUEST_CODE) { 40 | //在这儿,你可以再对权限进行检查,从而给出提示,或进行下一步操作 41 | checkPermission(); 42 | ToastUtils.info("从设置中返回"); 43 | } 44 | } 45 | 46 | //----------------以下是请求权限base,子类activity只需要重写checkPermission()方法即可----------------// 47 | 48 | /** 49 | * 检查权限,子类要申请权限,需要重写该方法 50 | * */ 51 | public void checkPermission() { 52 | } 53 | 54 | @Override 55 | public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { 56 | super.onRequestPermissionsResult(requestCode, permissions, grantResults); 57 | // 将结果转发给EasyPermissions 58 | EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this); 59 | } 60 | 61 | @Override 62 | public void onPermissionsGranted(int requestCode, @NonNull List perms) { 63 | } 64 | 65 | @Override 66 | public void onPermissionsDenied(int requestCode, @NonNull List perms) { 67 | 68 | //若是在权限弹窗中,用户勾选了'NEVER ASK AGAIN.'或者'不再提示',且拒绝权限。 69 | //跳转到设置界面去,让用户手动开启。 70 | if (EasyPermissions.somePermissionPermanentlyDenied(this, perms)) { 71 | 72 | String title = "需要权限,才能正常使用:"; 73 | String message = "如果没有请求的权限,此应用可能无法正常工作。请打开应用设置以修改应用权限。"; 74 | AlertDialogUtils.showDialog(this, title, message, "去设置", new QMUIDialogAction.ActionListener() { 75 | @Override 76 | public void onClick(QMUIDialog dialog, int index) { 77 | Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS); 78 | Uri uri = Uri.fromParts("package", MainApplication.getContext().getPackageName(), null); 79 | intent.setData(uri); 80 | startActivityForResult(intent, Constants.APP_SETTING_DIALOG_REQUEST_CODE); 81 | dialog.dismiss(); 82 | } 83 | }); 84 | } 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /app/src/main/java/com/bonait/bnframework/common/base/BaseFragment.java: -------------------------------------------------------------------------------- 1 | package com.bonait.bnframework.common.base; 2 | 3 | import android.content.Intent; 4 | import android.net.Uri; 5 | import android.provider.Settings; 6 | import android.support.annotation.NonNull; 7 | import android.support.annotation.Nullable; 8 | 9 | import com.bonait.bnframework.MainApplication; 10 | import com.bonait.bnframework.common.constant.Constants; 11 | import com.bonait.bnframework.common.utils.AlertDialogUtils; 12 | import com.bonait.bnframework.common.utils.ToastUtils; 13 | import com.qmuiteam.qmui.arch.QMUIFragment; 14 | import com.qmuiteam.qmui.util.QMUIDisplayHelper; 15 | import com.qmuiteam.qmui.widget.dialog.QMUIDialog; 16 | import com.qmuiteam.qmui.widget.dialog.QMUIDialogAction; 17 | 18 | import java.util.List; 19 | 20 | import pub.devrel.easypermissions.EasyPermissions; 21 | 22 | /** 23 | * Created by LY on 2019/3/25. 24 | */ 25 | public abstract class BaseFragment extends QMUIFragment implements EasyPermissions.PermissionCallbacks { 26 | 27 | public BaseFragment() { 28 | } 29 | 30 | @Override 31 | protected int backViewInitOffset() { 32 | return QMUIDisplayHelper.dp2px(requireContext(), 100); 33 | } 34 | 35 | @Override 36 | public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { 37 | super.onActivityResult(requestCode, resultCode, data); 38 | 39 | if (requestCode == Constants.APP_SETTING_DIALOG_REQUEST_CODE) { 40 | //在这儿,你可以再对权限进行检查,从而给出提示,或进行下一步操作 41 | checkPermission(); 42 | ToastUtils.info("从设置中返回"); 43 | } 44 | } 45 | 46 | //----------------以下是请求权限base,子类activity只需要重写checkPermission()方法即可----------------// 47 | 48 | /** 49 | * 检查权限,子类要申请权限,需要重写该方法 50 | * */ 51 | public void checkPermission() { 52 | } 53 | 54 | 55 | @Override 56 | public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { 57 | super.onRequestPermissionsResult(requestCode, permissions, grantResults); 58 | // 将结果转发给EasyPermissions 59 | EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this); 60 | } 61 | 62 | @Override 63 | public void onPermissionsGranted(int requestCode, @NonNull List perms) { 64 | } 65 | 66 | @Override 67 | public void onPermissionsDenied(int requestCode, @NonNull List perms) { 68 | 69 | //若是在权限弹窗中,用户勾选了'NEVER ASK AGAIN.'或者'不再提示',且拒绝权限。 70 | //跳转到设置界面去,让用户手动开启。 71 | if (EasyPermissions.somePermissionPermanentlyDenied(this, perms)) { 72 | 73 | String title = "需要权限,才能正常使用:"; 74 | String message = "如果没有请求的权限,此应用可能无法正常工作。请打开应用设置以修改应用权限。"; 75 | AlertDialogUtils.showDialog(getContext(), title, message, "去设置", new QMUIDialogAction.ActionListener() { 76 | @Override 77 | public void onClick(QMUIDialog dialog, int index) { 78 | Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS); 79 | Uri uri = Uri.fromParts("package", MainApplication.getContext().getPackageName(), null); 80 | intent.setData(uri); 81 | startActivityForResult(intent, Constants.APP_SETTING_DIALOG_REQUEST_CODE); 82 | dialog.dismiss(); 83 | } 84 | }); 85 | } 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /app/src/main/java/com/bonait/bnframework/common/base/BaseFragmentActivity.java: -------------------------------------------------------------------------------- 1 | package com.bonait.bnframework.common.base; 2 | 3 | import com.qmuiteam.qmui.arch.QMUIFragmentActivity; 4 | 5 | /** 6 | * Created by LY on 2019/3/27. 7 | */ 8 | public abstract class BaseFragmentActivity extends QMUIFragmentActivity { 9 | } 10 | -------------------------------------------------------------------------------- /app/src/main/java/com/bonait/bnframework/common/constant/Constants.java: -------------------------------------------------------------------------------- 1 | package com.bonait.bnframework.common.constant; 2 | 3 | import com.bonait.bnframework.R; 4 | import com.bonait.bnframework.MainApplication; 5 | 6 | /** 7 | * Created by LY on 2019/3/21. 8 | */ 9 | public interface Constants { 10 | 11 | String SERVICE_IP = "http://192.168.22.98:23104/GKIA"; 12 | String APP_TOKEN = "appToken"; 13 | 14 | // admin测试数据使用 15 | boolean SKIP_TO_TEST_ACTIVITY = false; // 是否启用TestActivity 16 | boolean superAdminTest = MainApplication.getContext().getResources().getBoolean(R.bool.superAdminTest); 17 | 18 | // OkGo 连接超时时间,毫秒ms 19 | long CONNECT_TIME_OUT = 6000; 20 | 21 | // 申请权限跳转到设置界面code 22 | int APP_SETTING_DIALOG_REQUEST_CODE = 1; 23 | 24 | // 申请权限code 25 | int ALL_PERMISSION = 100; 26 | 27 | // 更新apk 28 | int UPDATE_APP = 102; 29 | int INSTALL_PERMISSION_CODE = 103; 30 | 31 | } 32 | -------------------------------------------------------------------------------- /app/src/main/java/com/bonait/bnframework/common/constant/SPConstants.java: -------------------------------------------------------------------------------- 1 | package com.bonait.bnframework.common.constant; 2 | 3 | /** 4 | * Created by LY on 2019/4/4. 5 | * 保存到SharedPreferences的常量名字 6 | * 将SharedPreferences的key统一管理 7 | */ 8 | public interface SPConstants { 9 | 10 | /* 11 | * 将SharedPreferences的key统一管理 12 | * 13 | * */ 14 | 15 | /** 16 | * App token 17 | * */ 18 | String TOKEN = "token"; 19 | 20 | /** 21 | * 是否修改密码,Boolean 22 | * */ 23 | String CHANGE_PWD = "changePwd"; 24 | 25 | /** 26 | * 用户账号 27 | * */ 28 | String USER_NAME = "username"; 29 | 30 | /** 31 | * 用户密码 32 | * */ 33 | String PASSWORD = "password"; 34 | 35 | /** 36 | * 用户名字 37 | * */ 38 | String USER = "user"; 39 | 40 | /** 41 | * 用户ID 42 | * */ 43 | String USER_ID = "userId"; 44 | 45 | /** 46 | * 角色 47 | * */ 48 | String ROLE_NAMES = "roleNames"; 49 | 50 | /** 51 | * 部门 52 | * */ 53 | String FIRST_DEP_ID = "firstDepId"; 54 | 55 | 56 | } 57 | -------------------------------------------------------------------------------- /app/src/main/java/com/bonait/bnframework/common/http/GsonConvert.java: -------------------------------------------------------------------------------- 1 | package com.bonait.bnframework.common.http; 2 | 3 | import com.google.gson.Gson; 4 | import com.google.gson.JsonIOException; 5 | import com.google.gson.JsonSyntaxException; 6 | import com.google.gson.stream.JsonReader; 7 | 8 | import java.io.Reader; 9 | import java.lang.reflect.Type; 10 | 11 | /** 12 | * Created by LY on 2019/4/1. 13 | * Gson 转换 14 | */ 15 | public class GsonConvert { 16 | 17 | private static Gson create() { 18 | return GsonConvert.GsonHolder.gson; 19 | } 20 | 21 | private static class GsonHolder { 22 | private static Gson gson = new Gson(); 23 | } 24 | 25 | public static T fromJson(String json, Class type) throws JsonIOException, JsonSyntaxException { 26 | return create().fromJson(json, type); 27 | } 28 | 29 | public static T fromJson(String json, Type type) { 30 | return create().fromJson(json, type); 31 | } 32 | 33 | public static T fromJson(JsonReader reader, Type typeOfT) throws JsonIOException, JsonSyntaxException { 34 | return create().fromJson(reader, typeOfT); 35 | } 36 | 37 | public static T fromJson(Reader json, Class classOfT) throws JsonSyntaxException, JsonIOException { 38 | return create().fromJson(json, classOfT); 39 | } 40 | 41 | public static T fromJson(Reader json, Type typeOfT) throws JsonIOException, JsonSyntaxException { 42 | return create().fromJson(json, typeOfT); 43 | } 44 | 45 | public static String toJson(Object src) { 46 | return create().toJson(src); 47 | } 48 | 49 | public static String toJson(Object src, Type typeOfSrc) { 50 | return create().toJson(src, typeOfSrc); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /app/src/main/java/com/bonait/bnframework/common/http/callback/bitmap/BitmapDialogCallback.java: -------------------------------------------------------------------------------- 1 | package com.bonait.bnframework.common.http.callback.bitmap; 2 | 3 | import android.content.Context; 4 | import android.graphics.Bitmap; 5 | 6 | import com.lzy.okgo.callback.BitmapCallback; 7 | import com.lzy.okgo.request.base.Request; 8 | import com.qmuiteam.qmui.widget.dialog.QMUITipDialog; 9 | 10 | /** 11 | * Created by LY on 2019/4/2. 12 | * 13 | * 如果请求的数据是图片,则可以使用该回调,回调的图片进行了压缩处理,确保不发生OOM 14 | * 15 | * 有加载框的网络图片请求回调 16 | * 17 | */ 18 | public abstract class BitmapDialogCallback extends BitmapCallback { 19 | 20 | private QMUITipDialog tipDialog; 21 | 22 | 23 | public BitmapDialogCallback(Context context) { 24 | super(1000,1000); 25 | tipDialog = new QMUITipDialog.Builder(context) 26 | .setIconType(QMUITipDialog.Builder.ICON_TYPE_LOADING) 27 | .setTipWord("正在加载") 28 | .create(); 29 | } 30 | 31 | @Override 32 | public void onStart(Request request) { 33 | if (tipDialog != null && !tipDialog.isShowing()) { 34 | tipDialog.show(); 35 | } 36 | } 37 | 38 | @Override 39 | public void onFinish() { 40 | if (tipDialog != null && tipDialog.isShowing()) { 41 | tipDialog.dismiss(); 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /app/src/main/java/com/bonait/bnframework/common/http/callback/files/FileProgressDialogCallBack.java: -------------------------------------------------------------------------------- 1 | package com.bonait.bnframework.common.http.callback.files; 2 | 3 | import android.app.ProgressDialog; 4 | import android.content.Context; 5 | import android.content.DialogInterface; 6 | import android.text.format.Formatter; 7 | import android.util.Log; 8 | 9 | import com.bonait.bnframework.MainApplication; 10 | import com.bonait.bnframework.common.notification.DownloadNotification; 11 | import com.bonait.bnframework.common.utils.AlertDialogUtils; 12 | import com.bonait.bnframework.common.utils.NetworkUtils; 13 | import com.bonait.bnframework.common.utils.ToastUtils; 14 | import com.lzy.okgo.OkGo; 15 | import com.lzy.okgo.callback.FileCallback; 16 | import com.lzy.okgo.model.Progress; 17 | import com.lzy.okgo.model.Response; 18 | import com.lzy.okgo.request.base.Request; 19 | import com.qmuiteam.qmui.widget.dialog.QMUIDialog; 20 | import com.qmuiteam.qmui.widget.dialog.QMUIDialogAction; 21 | 22 | import java.io.File; 23 | import java.util.Locale; 24 | 25 | /** 26 | * Created by LY on 2019/4/15. 27 | * 带加载进度条的下载回调接口,默认OkGo文件回调 28 | */ 29 | public abstract class FileProgressDialogCallBack extends FileCallback { 30 | 31 | private ProgressDialog progressDialog; 32 | private DownloadNotification downloadNotification; 33 | 34 | public FileProgressDialogCallBack(Context context) { 35 | super(null); 36 | initDialog(context); 37 | } 38 | 39 | public FileProgressDialogCallBack(Context context, String destFileName) { 40 | super(destFileName); 41 | initDialog(context); 42 | } 43 | 44 | public FileProgressDialogCallBack(Context context, String destFileDir, String destFileName) { 45 | super(destFileDir, destFileName); 46 | initDialog(context); 47 | } 48 | 49 | 50 | @Override 51 | public void onStart(Request request) { 52 | if (progressDialog != null && !progressDialog.isShowing()) { 53 | progressDialog.show(); 54 | } 55 | } 56 | 57 | @Override 58 | public void onFinish() { 59 | if (progressDialog != null && progressDialog.isShowing()) { 60 | progressDialog.dismiss(); 61 | } 62 | 63 | if (downloadNotification != null) { 64 | downloadNotification.downloadComplete(); 65 | } 66 | } 67 | 68 | @Override 69 | public void onError(Response response) { 70 | super.onError(response); 71 | if (downloadNotification != null) { 72 | downloadNotification.downloadError(); 73 | } 74 | 75 | ToastUtils.error(response.body().getName() + "下载失败,请重新下载!"); 76 | if (progressDialog != null && progressDialog.isShowing()) { 77 | progressDialog.dismiss(); 78 | } 79 | } 80 | 81 | @Override 82 | public void downloadProgress(Progress progress) { 83 | String downloadLength = Formatter.formatFileSize(MainApplication.getContext(), progress.currentSize); 84 | String totalLength = Formatter.formatFileSize(MainApplication.getContext(), progress.totalSize); 85 | 86 | if (progress.totalSize > 0) { 87 | progressDialog.setMax((int) progress.totalSize); 88 | } 89 | progressDialog.setProgress((int) (progress.fraction * progress.totalSize)); 90 | progressDialog.setProgressNumberFormat(String.format(Locale.CHINA, "%s / %s", downloadLength, totalLength)); 91 | Log.d("downloadProgress", progress.fileName + " 下载中……" + String.format(Locale.CHINA, "%s / %s", downloadLength, totalLength)); 92 | 93 | if (downloadNotification != null) { 94 | downloadNotification.showProgress(progress); 95 | } 96 | } 97 | 98 | /** 99 | * 判断网络状态。移动/WiFi,弹出警告框 100 | */ 101 | private void initDialog(final Context context) { 102 | if (NetworkUtils.isActiveNetworkMobile(context)) { 103 | String title = "温馨提示!"; 104 | String message = "当前网络为移动网络,可能会消耗大量移动流量数据,确定要下载吗?"; 105 | AlertDialogUtils.showDialog(context, title, message, new QMUIDialogAction.ActionListener() { 106 | @Override 107 | public void onClick(QMUIDialog dialog, int index) { 108 | downloadingDialog(context); 109 | dialog.dismiss(); 110 | } 111 | }); 112 | } else { 113 | downloadingDialog(context); 114 | } 115 | } 116 | 117 | /** 118 | * 显示进度条对话框 119 | * */ 120 | private void downloadingDialog(final Context context) { 121 | progressDialog = new ProgressDialog(context); 122 | progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); 123 | progressDialog.setCancelable(false); 124 | progressDialog.setCanceledOnTouchOutside(false); 125 | progressDialog.setTitle("正在下载"); 126 | 127 | progressDialog.setButton(DialogInterface.BUTTON_NEGATIVE, "停止下载", new DialogInterface.OnClickListener() { 128 | @Override 129 | public void onClick(DialogInterface dialog, int which) { 130 | OkGo.getInstance().cancelTag(context); 131 | ToastUtils.info("已停止下载!"); 132 | dialog.dismiss(); 133 | } 134 | }); 135 | 136 | progressDialog.setButton(DialogInterface.BUTTON_POSITIVE, "后台下载", new DialogInterface.OnClickListener() { 137 | @Override 138 | public void onClick(DialogInterface dialog, int which) { 139 | downloadNotification = new DownloadNotification(context); 140 | dialog.dismiss(); 141 | } 142 | }); 143 | } 144 | 145 | } 146 | -------------------------------------------------------------------------------- /app/src/main/java/com/bonait/bnframework/common/http/callback/files2/FileCallback2.java: -------------------------------------------------------------------------------- 1 | package com.bonait.bnframework.common.http.callback.files2; 2 | 3 | import com.lzy.okgo.callback.AbsCallback; 4 | 5 | import java.io.File; 6 | 7 | import okhttp3.Response; 8 | 9 | /** 10 | * Created by LY on 2019/4/10. 11 | *

与OkGo的FileCallback改动不大,如果不想使用该类,可直接使用OkGo默认的FileCallback

12 | *

将文件转换类改成FileConvert2

13 | * 14 | */ 15 | public abstract class FileCallback2 extends AbsCallback { 16 | 17 | //文件转换类FileConvert2 18 | private FileConvert2 convert; 19 | 20 | public FileCallback2(long totalSize) { 21 | this(null,totalSize); 22 | } 23 | 24 | public FileCallback2(String destFileName,long totalSize) { 25 | this(null, destFileName,totalSize); 26 | } 27 | 28 | public FileCallback2(String destFileDir, String destFileName,long totalSize) { 29 | // FileConvert2 30 | convert = new FileConvert2(destFileDir, destFileName,totalSize); 31 | convert.setCallback(this); 32 | } 33 | 34 | @Override 35 | public File convertResponse(Response response) throws Throwable { 36 | File file = convert.convertResponse(response); 37 | response.close(); 38 | return file; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /app/src/main/java/com/bonait/bnframework/common/http/callback/files2/FileConvert2.java: -------------------------------------------------------------------------------- 1 | package com.bonait.bnframework.common.http.callback.files2; 2 | 3 | import android.os.Environment; 4 | import android.text.TextUtils; 5 | 6 | import com.lzy.okgo.callback.Callback; 7 | import com.lzy.okgo.convert.Converter; 8 | import com.lzy.okgo.model.Progress; 9 | import com.lzy.okgo.utils.HttpUtils; 10 | import com.lzy.okgo.utils.IOUtils; 11 | 12 | import java.io.File; 13 | import java.io.FileOutputStream; 14 | import java.io.InputStream; 15 | 16 | import okhttp3.Response; 17 | import okhttp3.ResponseBody; 18 | 19 | /** 20 | * Created by LY on 2019/4/10. 21 | * 与OkGo的FileConvert改动不大,如果不想使用该类,可直接使用OkGo默认的FileConvert 22 | *

与OkGo的FileConvert改动不大

23 | *

只是将代码的 progress.totalSize = body.contentLength();

24 | *

替换成progress.totalSize = totalSize; 其中totalSize为形参,需要自己传参

25 | * 26 | */ 27 | public class FileConvert2 implements Converter { 28 | 29 | public static final String DM_TARGET_FOLDER = File.separator + "download" + File.separator; //下载目标文件夹 30 | 31 | private String folder; //目标文件存储的文件夹路径 32 | private String fileName; //目标文件存储的文件名 33 | private Callback callback; //下载回调 34 | 35 | /** 36 | * 文件总大小 37 | * */ 38 | private long totalSize; 39 | 40 | public FileConvert2(long totalSize) { 41 | this(null,totalSize); 42 | this.totalSize = totalSize; 43 | } 44 | 45 | public FileConvert2(String fileName, long totalSize) { 46 | this(Environment.getExternalStorageDirectory() + DM_TARGET_FOLDER, fileName,totalSize); 47 | this.totalSize = totalSize; 48 | } 49 | 50 | public FileConvert2(String folder, String fileName,long totalSize) { 51 | this.folder = folder; 52 | this.fileName = fileName; 53 | this.totalSize = totalSize; 54 | } 55 | 56 | public void setCallback(Callback callback) { 57 | this.callback = callback; 58 | } 59 | 60 | @Override 61 | public File convertResponse(Response response) throws Throwable { 62 | String url = response.request().url().toString(); 63 | if (TextUtils.isEmpty(folder)) folder = Environment.getExternalStorageDirectory() + DM_TARGET_FOLDER; 64 | if (TextUtils.isEmpty(fileName)) fileName = HttpUtils.getNetFileName(response, url); 65 | 66 | File dir = new File(folder); 67 | IOUtils.createFolder(dir); 68 | File file = new File(dir, fileName); 69 | IOUtils.delFileOrFolder(file); 70 | 71 | InputStream bodyStream = null; 72 | byte[] buffer = new byte[8192]; 73 | FileOutputStream fileOutputStream = null; 74 | try { 75 | ResponseBody body = response.body(); 76 | if (body == null) return null; 77 | 78 | bodyStream = body.byteStream(); 79 | Progress progress = new Progress(); 80 | progress.totalSize = totalSize; 81 | progress.fileName = fileName; 82 | progress.filePath = file.getAbsolutePath(); 83 | progress.status = Progress.LOADING; 84 | progress.url = url; 85 | progress.tag = url; 86 | 87 | int len; 88 | fileOutputStream = new FileOutputStream(file); 89 | while ((len = bodyStream.read(buffer)) != -1) { 90 | fileOutputStream.write(buffer, 0, len); 91 | 92 | if (callback == null) continue; 93 | Progress.changeProgress(progress, len, new Progress.Action() { 94 | @Override 95 | public void call(Progress progress) { 96 | onProgress(progress); 97 | } 98 | }); 99 | } 100 | fileOutputStream.flush(); 101 | return file; 102 | } finally { 103 | IOUtils.closeQuietly(bodyStream); 104 | IOUtils.closeQuietly(fileOutputStream); 105 | } 106 | } 107 | 108 | private void onProgress(final Progress progress) { 109 | HttpUtils.runOnUiThread(new Runnable() { 110 | @Override 111 | public void run() { 112 | callback.downloadProgress(progress); //进度回调的方法 113 | } 114 | }); 115 | } 116 | 117 | } 118 | -------------------------------------------------------------------------------- /app/src/main/java/com/bonait/bnframework/common/http/callback/files2/FileProgressDialogCallBack2.java: -------------------------------------------------------------------------------- 1 | package com.bonait.bnframework.common.http.callback.files2; 2 | 3 | import android.app.ProgressDialog; 4 | import android.content.Context; 5 | import android.content.DialogInterface; 6 | import android.text.format.Formatter; 7 | import android.util.Log; 8 | 9 | import com.bonait.bnframework.MainApplication; 10 | import com.bonait.bnframework.common.notification.DownloadNotification; 11 | import com.bonait.bnframework.common.utils.AlertDialogUtils; 12 | import com.bonait.bnframework.common.utils.NetworkUtils; 13 | import com.bonait.bnframework.common.utils.ToastUtils; 14 | import com.lzy.okgo.OkGo; 15 | import com.lzy.okgo.model.Progress; 16 | import com.lzy.okgo.model.Response; 17 | import com.lzy.okgo.request.base.Request; 18 | import com.qmuiteam.qmui.widget.dialog.QMUIDialog; 19 | import com.qmuiteam.qmui.widget.dialog.QMUIDialogAction; 20 | 21 | import java.io.File; 22 | import java.util.Locale; 23 | 24 | /** 25 | * Created by LY on 2019/4/10. 26 | * 带加载进度条的下载回调接口,自定义的文件回调 27 | */ 28 | public abstract class FileProgressDialogCallBack2 extends FileCallback2 { 29 | 30 | private ProgressDialog progressDialog; 31 | private DownloadNotification downloadNotification; 32 | 33 | 34 | public FileProgressDialogCallBack2(Context context, long totalSize) { 35 | super(totalSize); 36 | initDialog(context, totalSize); 37 | } 38 | 39 | public FileProgressDialogCallBack2(Context context, String destFileName, long totalSize) { 40 | super(destFileName, totalSize); 41 | initDialog(context, totalSize); 42 | } 43 | 44 | public FileProgressDialogCallBack2(Context context, String destFileDir, String destFileName, long totalSize) { 45 | super(destFileDir, destFileName, totalSize); 46 | initDialog(context, totalSize); 47 | } 48 | 49 | @Override 50 | public void onStart(Request request) { 51 | if (progressDialog != null && !progressDialog.isShowing()) { 52 | progressDialog.show(); 53 | } 54 | } 55 | 56 | @Override 57 | public void onFinish() { 58 | if (progressDialog != null && progressDialog.isShowing()) { 59 | progressDialog.dismiss(); 60 | } 61 | 62 | if (downloadNotification != null) { 63 | downloadNotification.downloadComplete(); 64 | } 65 | } 66 | 67 | @Override 68 | public void onError(Response response) { 69 | super.onError(response); 70 | if (downloadNotification != null) { 71 | downloadNotification.downloadError(); 72 | } 73 | 74 | ToastUtils.error(response.body().getName() + "下载失败,请重新下载!"); 75 | if (progressDialog != null && progressDialog.isShowing()) { 76 | progressDialog.dismiss(); 77 | } 78 | } 79 | 80 | @Override 81 | public void downloadProgress(Progress progress) { 82 | String downloadLength = Formatter.formatFileSize(MainApplication.getContext(), progress.currentSize); 83 | String totalLength = Formatter.formatFileSize(MainApplication.getContext(), progress.totalSize); 84 | 85 | progressDialog.setProgress((int) (progress.fraction * progress.totalSize)); 86 | progressDialog.setProgressNumberFormat(String.format(Locale.CHINA, "%sMb / %sMb", downloadLength, totalLength)); 87 | Log.d("downloadProgress", progress.fileName + " 下载中……" + String.format(Locale.CHINA, "%s / %s", downloadLength, totalLength)); 88 | 89 | if (downloadNotification != null) { 90 | downloadNotification.showProgress(progress); 91 | } 92 | } 93 | 94 | /** 95 | * 判断网络状态。移动/WiFi,弹出警告框 96 | */ 97 | private void initDialog(final Context context, final long totalSize) { 98 | if (NetworkUtils.isActiveNetworkMobile(context)) { 99 | String title = "温馨提示!"; 100 | String message = "当前网络为移动网络,可能会消耗大量移动流量数据,确定要下载吗?"; 101 | AlertDialogUtils.showDialog(context, title, message, new QMUIDialogAction.ActionListener() { 102 | @Override 103 | public void onClick(QMUIDialog dialog, int index) { 104 | downloadingDialog(context, totalSize); 105 | dialog.dismiss(); 106 | } 107 | }); 108 | } else { 109 | downloadingDialog(context, totalSize); 110 | } 111 | } 112 | 113 | /** 114 | * 显示进度条对话框 115 | * */ 116 | private void downloadingDialog(final Context context, long totalSize) { 117 | progressDialog = new ProgressDialog(context); 118 | progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); 119 | progressDialog.setCancelable(false); 120 | progressDialog.setCanceledOnTouchOutside(false); 121 | progressDialog.setTitle("正在下载"); 122 | 123 | if (totalSize > 0) { 124 | progressDialog.setMax((int) totalSize); 125 | } 126 | 127 | progressDialog.setButton(DialogInterface.BUTTON_NEGATIVE, "停止下载", new DialogInterface.OnClickListener() { 128 | @Override 129 | public void onClick(DialogInterface dialog, int which) { 130 | OkGo.getInstance().cancelTag(context); 131 | ToastUtils.info("已停止下载!"); 132 | dialog.dismiss(); 133 | } 134 | }); 135 | 136 | progressDialog.setButton(DialogInterface.BUTTON_POSITIVE, "后台下载", new DialogInterface.OnClickListener() { 137 | @Override 138 | public void onClick(DialogInterface dialog, int which) { 139 | downloadNotification = new DownloadNotification(context); 140 | dialog.dismiss(); 141 | } 142 | }); 143 | } 144 | 145 | } 146 | -------------------------------------------------------------------------------- /app/src/main/java/com/bonait/bnframework/common/http/callback/files2/ReadMe.txt: -------------------------------------------------------------------------------- 1 | 由于一些服务器http返回头的原因:在文件下载中, 2 | 响应头为:Transfer-Encoding: chunked; 3 | 请求头为:Accept-Encoding: gzip, deflate; 4 | 且没有返回Content-Length这个响应头,或者Content-Length = -1。 5 | 这样的http请求是以压缩gzip形式动态下载,文件下载总大小是无法预知的。所以使用一般的默认的fileCallback回调接口,进度条是呈现不出来进度的。 6 | 7 | 小提示:Transfer-Encoding: chunked;与 Content-Length 这两个响应头二者只能存在一个,即使两者都有,Content-Length也会默认失效。 8 | 9 | //---------------------------------------------------------------------------------------------// 10 | 11 | 由于OkGo里的OkDownload主要功能必须要添加Content-Length这个响应头,才能获取文件大小。 12 | (OkGo原文说明:服务端一定要返回Content-Length,注意,是一定要返回Content-Length这个响应头,如果没有,该值默认是-1, 13 | 这个值表示当前要下载的文件有多大,如果服务端不给的话,客户端在下载过程中是不可能知道我要下载的文件有多大的,所以常见的问题就是进度是负数。) 14 | 15 | 为了应对这种情况,在这个包中重写了fileCallback和fileConvert这两个类,开放文件总大小totalSize这个参数。 16 | 因此,需要自己传参文件总大小。(文件大小必须为实际大小byte,不然进度条会出现奇怪的问题) 17 | 18 | //---------------------------------------------------------------------------------------------// 19 | 20 | 如果后台服务器有Content-Length,并且不是gzip压缩,则可以使用file包下的FileProgressDialogCallBack或者FileCallback回调。 21 | 如果后台服务器没有Content-Length或者Content-Length = -1,且是gzip压缩,则可以使用file2包下的FileProgressDialogCallBack2或者FileCallback2回调,并传入totalSize参数。 -------------------------------------------------------------------------------- /app/src/main/java/com/bonait/bnframework/common/http/callback/json/JsonCallback.java: -------------------------------------------------------------------------------- 1 | package com.bonait.bnframework.common.http.callback.json; 2 | 3 | import android.app.Activity; 4 | import android.content.Intent; 5 | 6 | import com.bonait.bnframework.manager.ActivityLifecycleManager; 7 | import com.bonait.bnframework.common.constant.SPConstants; 8 | import com.bonait.bnframework.common.http.exception.TokenException; 9 | import com.bonait.bnframework.common.utils.PreferenceUtils; 10 | import com.bonait.bnframework.common.utils.ToastUtils; 11 | import com.bonait.bnframework.modules.welcome.activity.WelcomeActivity; 12 | import com.lzy.okgo.callback.AbsCallback; 13 | import com.lzy.okgo.exception.HttpException; 14 | import com.lzy.okgo.exception.StorageException; 15 | import com.lzy.okgo.model.Response; 16 | 17 | import java.lang.reflect.ParameterizedType; 18 | import java.lang.reflect.Type; 19 | import java.net.ConnectException; 20 | import java.net.SocketTimeoutException; 21 | import java.net.UnknownHostException; 22 | 23 | /** 24 | * Created by LY on 2019/4/2. 25 | */ 26 | public abstract class JsonCallback extends AbsCallback { 27 | 28 | private Type type; 29 | private Class clazz; 30 | 31 | public JsonCallback() { 32 | } 33 | 34 | public JsonCallback(Type type) { 35 | this.type = type; 36 | } 37 | 38 | public JsonCallback(Class clazz) { 39 | this.clazz = clazz; 40 | } 41 | 42 | /** 43 | * 该方法是子线程处理,不能做ui相关的工作 44 | * 主要作用是解析网络返回的 response 对象,生产onSuccess回调中需要的数据对象 45 | * 这里的解析工作不同的业务逻辑基本都不一样,所以需要自己实现,实际使用根据需要修改 46 | */ 47 | @Override 48 | public T convertResponse(okhttp3.Response response) throws Throwable { 49 | 50 | // 不同的业务,这里的代码逻辑都不一样,如果你不修改,那么基本不可用 51 | 52 | //详细自定义的原理和文档,看这里: https://github.com/jeasonlzy/okhttp-OkGo/wiki/JsonCallback 53 | 54 | if (type == null) { 55 | if (clazz == null) { 56 | Type genType = getClass().getGenericSuperclass(); 57 | type = ((ParameterizedType) genType).getActualTypeArguments()[0]; 58 | } else { 59 | JsonConvert convert = new JsonConvert<>(clazz); 60 | return convert.convertResponse(response); 61 | } 62 | } 63 | 64 | JsonConvert convert = new JsonConvert<>(type); 65 | return convert.convertResponse(response); 66 | } 67 | 68 | 69 | @Override 70 | public void onError(Response response) { 71 | super.onError(response); 72 | 73 | Throwable exception = response.getException(); 74 | //如果OkGo配置中Logger日志已打开,super.onError(response);就已经将printStackTrace打印出来了 75 | /*if (exception != null) { 76 | exception.printStackTrace(); 77 | }*/ 78 | 79 | if (exception instanceof UnknownHostException || exception instanceof ConnectException) { 80 | ToastUtils.error("网络连接失败,请连接网络!"); 81 | } else if (exception instanceof SocketTimeoutException) { 82 | ToastUtils.error("网络请求超时,请稍后重试!"); 83 | } else if (exception instanceof HttpException) { 84 | ToastUtils.error("暂时无法连接服务器,请稍后重试!"); 85 | } else if (exception instanceof StorageException) { 86 | ToastUtils.error("SD卡不存在或者没有获取SD卡访问权限!"); 87 | } else if (exception instanceof TokenException) { 88 | // 删除token,跳转到登录页面 89 | skipLoginActivityAndFinish(exception); 90 | } else if (exception instanceof IllegalStateException) { 91 | ToastUtils.error(exception.getMessage()); 92 | } 93 | } 94 | 95 | /** 96 | * 删除token,跳转到登录页面 97 | * */ 98 | private void skipLoginActivityAndFinish(Throwable exception) { 99 | //删除本地过期的token 100 | PreferenceUtils.remove(SPConstants.TOKEN); 101 | PreferenceUtils.remove(SPConstants.USER_ID); 102 | Intent intent = new Intent("com.bonait.bnframework.modules.welcome.activity.LoginActivity.ACTION_START"); 103 | // 获取当前Activity(栈中最后一个压入的) 104 | Activity activity = ActivityLifecycleManager.get().currentActivity(); 105 | 106 | // 如果不是WelcomeActivity,显示Toast告知token已过期 107 | if (activity.getClass() != WelcomeActivity.class) { 108 | ToastUtils.info(exception.getMessage()); 109 | } 110 | 111 | // 结束所有Activity 112 | ActivityLifecycleManager.get().finishAllActivity(); 113 | // 跳转到登录页面 114 | activity.startActivity(intent); 115 | activity.overridePendingTransition(android.R.anim.fade_in, android.R.anim.fade_out); 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /app/src/main/java/com/bonait/bnframework/common/http/callback/json/JsonDialogCallback.java: -------------------------------------------------------------------------------- 1 | package com.bonait.bnframework.common.http.callback.json; 2 | 3 | import android.content.Context; 4 | 5 | import com.lzy.okgo.request.base.Request; 6 | import com.qmuiteam.qmui.widget.dialog.QMUITipDialog; 7 | 8 | /** 9 | * Created by LY on 2019/4/1. 10 | * 11 | * 在网络请求前显示一个loading,请求结束后取消loading 12 | * 13 | * 有加载框的网络请求回调 14 | * 15 | */ 16 | public abstract class JsonDialogCallback extends JsonCallback { 17 | 18 | private QMUITipDialog tipDialog; 19 | 20 | /** 21 | * 弹出加载框入口 22 | * */ 23 | public JsonDialogCallback(Context context) { 24 | super(); 25 | initDialog(context); 26 | } 27 | 28 | /** 29 | * 初始化加载框 30 | * */ 31 | private void initDialog(Context context) { 32 | tipDialog = new QMUITipDialog.Builder(context) 33 | .setIconType(QMUITipDialog.Builder.ICON_TYPE_LOADING) 34 | .setTipWord("正在加载") 35 | .create(); 36 | } 37 | 38 | /** 39 | * 请求网络开始前弹出加载框 40 | * */ 41 | @Override 42 | public void onStart(Request request) { 43 | if (tipDialog != null && !tipDialog.isShowing()) { 44 | tipDialog.show(); 45 | } 46 | } 47 | 48 | /** 49 | * 请求网络结束后关闭加载框 50 | * */ 51 | @Override 52 | public void onFinish() { 53 | if (tipDialog != null && tipDialog.isShowing()) { 54 | tipDialog.dismiss(); 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /app/src/main/java/com/bonait/bnframework/common/http/callback/strings/StringDialogCallback.java: -------------------------------------------------------------------------------- 1 | package com.bonait.bnframework.common.http.callback.strings; 2 | 3 | import android.content.Context; 4 | 5 | import com.lzy.okgo.callback.StringCallback; 6 | import com.lzy.okgo.request.base.Request; 7 | import com.qmuiteam.qmui.widget.dialog.QMUITipDialog; 8 | 9 | /** 10 | * Created by LY on 2019/4/2. 11 | * 12 | * 对convertResponse()按文本解析,解析的编码依据服务端响应头中的Content-Type中的编码格式,自动进行编码转换,确保不出现乱码 13 | * 14 | * 有加载框的文本解析回调 15 | * 16 | */ 17 | public abstract class StringDialogCallback extends StringCallback { 18 | 19 | private QMUITipDialog tipDialog; 20 | 21 | /** 22 | * 展示加载框 23 | * */ 24 | public StringDialogCallback(Context context) { 25 | tipDialog = new QMUITipDialog.Builder(context) 26 | .setIconType(QMUITipDialog.Builder.ICON_TYPE_LOADING) 27 | .setTipWord("正在加载") 28 | .create(); 29 | } 30 | 31 | 32 | /** 33 | * 请求网络开始前弹出加载框 34 | * */ 35 | @Override 36 | public void onStart(Request request) { 37 | if (tipDialog != null && !tipDialog.isShowing()) { 38 | tipDialog.show(); 39 | } 40 | } 41 | 42 | /** 43 | * 请求网络结束后关闭加载框 44 | * */ 45 | @Override 46 | public void onFinish() { 47 | if (tipDialog != null && tipDialog.isShowing()) { 48 | tipDialog.dismiss(); 49 | } 50 | } 51 | 52 | } 53 | -------------------------------------------------------------------------------- /app/src/main/java/com/bonait/bnframework/common/http/exception/TokenException.java: -------------------------------------------------------------------------------- 1 | package com.bonait.bnframework.common.http.exception; 2 | 3 | /** 4 | * Created by LY on 2019/4/3. 5 | */ 6 | public class TokenException extends RuntimeException { 7 | 8 | private static final long serialVersionUID = 8394950517718638426L; 9 | 10 | 11 | public TokenException() { 12 | super(); 13 | } 14 | 15 | public TokenException(String message) { 16 | super(message); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /app/src/main/java/com/bonait/bnframework/common/interfaces/OnDoIntListener.java: -------------------------------------------------------------------------------- 1 | package com.bonait.bnframework.common.interfaces; 2 | 3 | /** 4 | * Created by LY on 2019/3/28. 5 | * 动画工具类接口监听 6 | */ 7 | public interface OnDoIntListener { 8 | void doSomething(int intValue); 9 | } 10 | -------------------------------------------------------------------------------- /app/src/main/java/com/bonait/bnframework/common/model/BaseCodeJson.java: -------------------------------------------------------------------------------- 1 | package com.bonait.bnframework.common.model; 2 | 3 | import com.google.gson.annotations.SerializedName; 4 | 5 | import java.io.Serializable; 6 | 7 | /** 8 | * Created by LY on 2019/4/2. 9 | */ 10 | public class BaseCodeJson implements Serializable { 11 | 12 | private static final long serialVersionUID = -2849146113542167339L; 13 | 14 | @SerializedName("code") 15 | private int code; 16 | @SerializedName("msg") 17 | private String msg; 18 | @SerializedName(value = "result" , alternate = {"data"}) 19 | private T result; 20 | 21 | 22 | @SerializedName("userId") 23 | private int userId; 24 | 25 | public int getCode() { 26 | return code; 27 | } 28 | 29 | public void setCode(int code) { 30 | this.code = code; 31 | } 32 | 33 | public String getMsg() { 34 | return msg; 35 | } 36 | 37 | public void setMsg(String msg) { 38 | this.msg = msg; 39 | } 40 | 41 | public T getResult() { 42 | return result; 43 | } 44 | 45 | public void setResult(T result) { 46 | this.result = result; 47 | } 48 | 49 | public int getUserId() { 50 | return userId; 51 | } 52 | 53 | public void setUserId(int userId) { 54 | this.userId = userId; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /app/src/main/java/com/bonait/bnframework/common/model/BaseJson.java: -------------------------------------------------------------------------------- 1 | package com.bonait.bnframework.common.model; 2 | 3 | import com.google.gson.annotations.SerializedName; 4 | 5 | import java.io.Serializable; 6 | 7 | /** 8 | * Created by LY on 2019/4/2. 9 | */ 10 | public class BaseJson implements Serializable { 11 | 12 | private static final long serialVersionUID = 477369592714415773L; 13 | 14 | @SerializedName("success") 15 | private boolean success; 16 | 17 | @SerializedName("totalCounts") 18 | private String totalCounts; 19 | 20 | @SerializedName(value = "result" , alternate = {"data"}) 21 | private T result; 22 | 23 | private String msg; 24 | 25 | 26 | public boolean isSuccess() { 27 | return success; 28 | } 29 | 30 | public void setSuccess(boolean success) { 31 | this.success = success; 32 | } 33 | 34 | public String getTotalCounts() { 35 | return totalCounts; 36 | } 37 | 38 | public void setTotalCounts(String totalCounts) { 39 | this.totalCounts = totalCounts; 40 | } 41 | 42 | public T getResult() { 43 | return result; 44 | } 45 | 46 | public void setResult(T result) { 47 | this.result = result; 48 | } 49 | 50 | public String getMsg() { 51 | return msg; 52 | } 53 | 54 | public void setMsg(String msg) { 55 | this.msg = msg; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /app/src/main/java/com/bonait/bnframework/common/model/SimpleBaseJson.java: -------------------------------------------------------------------------------- 1 | package com.bonait.bnframework.common.model; 2 | 3 | import com.google.gson.annotations.SerializedName; 4 | 5 | import java.io.Serializable; 6 | 7 | /** 8 | * Created by LY on 2019/4/2. 9 | */ 10 | public class SimpleBaseJson implements Serializable { 11 | 12 | @SerializedName("success") 13 | private boolean success; 14 | 15 | private String msg; 16 | 17 | public BaseJson toBaseJson() { 18 | BaseJson baseJson = new BaseJson(); 19 | baseJson.setSuccess(success); 20 | baseJson.setMsg(msg); 21 | return baseJson; 22 | } 23 | 24 | public boolean isSuccess() { 25 | return success; 26 | } 27 | 28 | public void setSuccess(boolean success) { 29 | this.success = success; 30 | } 31 | 32 | public String getMsg() { 33 | return msg; 34 | } 35 | 36 | public void setMsg(String msg) { 37 | this.msg = msg; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /app/src/main/java/com/bonait/bnframework/common/model/SimpleCodeJson.java: -------------------------------------------------------------------------------- 1 | package com.bonait.bnframework.common.model; 2 | 3 | import com.google.gson.annotations.SerializedName; 4 | 5 | /** 6 | * Created by LY on 2019/4/3. 7 | */ 8 | public class SimpleCodeJson { 9 | 10 | @SerializedName("code") 11 | private int code; 12 | @SerializedName("msg") 13 | private String msg; 14 | 15 | 16 | public BaseCodeJson toBaseCodeJson() { 17 | BaseCodeJson baseCodeJson = new BaseCodeJson(); 18 | baseCodeJson.setCode(code); 19 | baseCodeJson.setMsg(msg); 20 | return baseCodeJson; 21 | } 22 | 23 | public int getCode() { 24 | return code; 25 | } 26 | 27 | public void setCode(int code) { 28 | this.code = code; 29 | } 30 | 31 | public String getMsg() { 32 | return msg; 33 | } 34 | 35 | public void setMsg(String msg) { 36 | this.msg = msg; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /app/src/main/java/com/bonait/bnframework/common/notification/DownloadNotification.java: -------------------------------------------------------------------------------- 1 | package com.bonait.bnframework.common.notification; 2 | 3 | import android.app.Notification; 4 | import android.app.NotificationManager; 5 | import android.content.Context; 6 | import android.graphics.BitmapFactory; 7 | import android.support.v4.app.NotificationCompat; 8 | import android.text.format.Formatter; 9 | 10 | import com.bonait.bnframework.R; 11 | import com.bonait.bnframework.MainApplication; 12 | import com.lzy.okgo.model.Progress; 13 | 14 | import java.util.Date; 15 | import java.util.Locale; 16 | 17 | 18 | /** 19 | * Created by LY on 2019/4/18. 20 | * 下载通知栏notification 21 | */ 22 | public class DownloadNotification { 23 | 24 | private Context context; 25 | private int notificationId; 26 | private String Tag = "downloading"; // 下载通知栏标识 27 | private String downloadFileName; // 下载文件名称 28 | 29 | public DownloadNotification(Context context) { 30 | notificationId = (int) new Date().getTime(); 31 | this.context = context; 32 | } 33 | 34 | /** 35 | * 显示notification下载进度 36 | * */ 37 | public void showProgress(Progress progress) { 38 | downloadFileName = progress.fileName; 39 | String downloadLength = Formatter.formatFileSize(MainApplication.getContext(), progress.currentSize); 40 | String totalLength = Formatter.formatFileSize(MainApplication.getContext(), progress.totalSize); 41 | 42 | NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); 43 | Notification notification = new NotificationCompat.Builder(context, MainNotification.CHANNEL_DOWNLOADING_ID) 44 | .setSmallIcon(R.drawable.icon_user_pic) 45 | .setLargeIcon(BitmapFactory.decodeResource(context.getResources(), R.drawable.icon_user_pic)) 46 | .setContentTitle(progress.fileName) 47 | .setContentText("下载进度:" + String.format(Locale.CHINA, "%s / %s", downloadLength, totalLength)) 48 | .setProgress(100, (int) (progress.fraction * 100.0), false) 49 | .setDefaults(NotificationCompat.FLAG_ONLY_ALERT_ONCE) 50 | .build(); 51 | 52 | if (notificationManager != null) { 53 | notificationManager.notify(Tag,notificationId,notification); 54 | } 55 | } 56 | 57 | /** 58 | * 下载完成,关闭进度条通知栏,显示成功通知栏 59 | * */ 60 | public void downloadComplete() { 61 | int downloadCompleteId = (int) new Date().getTime(); 62 | NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); 63 | 64 | Notification notification = new NotificationCompat.Builder(context, MainNotification.CHANNEL_DOWNLOAD_COMPLETE_ID) 65 | .setSmallIcon(R.drawable.icon_user_pic) 66 | .setLargeIcon(BitmapFactory.decodeResource(context.getResources(), R.drawable.icon_user_pic)) 67 | .setContentTitle(downloadFileName) 68 | .setContentText("下载完成!") 69 | .setPriority(NotificationCompat.PRIORITY_MAX) 70 | .setAutoCancel(true) 71 | .build(); 72 | if (notificationManager != null) { 73 | notificationManager.notify(downloadCompleteId,notification); 74 | notificationManager.cancel(Tag,notificationId); 75 | } 76 | } 77 | 78 | /** 79 | * 下载错误,关闭进度条通知栏,显示错误通知栏 80 | * */ 81 | public void downloadError() { 82 | int downloadCompleteId = (int) new Date().getTime(); 83 | NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); 84 | 85 | Notification notification = new NotificationCompat.Builder(context, MainNotification.CHANNEL_DOWNLOAD_COMPLETE_ID) 86 | .setSmallIcon(R.drawable.icon_user_pic) 87 | .setLargeIcon(BitmapFactory.decodeResource(context.getResources(), R.drawable.icon_user_pic)) 88 | .setContentTitle(downloadFileName) 89 | .setContentText("下载失败,请重新下载!") 90 | .setAutoCancel(true) 91 | .build(); 92 | if (notificationManager != null) { 93 | notificationManager.notify(downloadCompleteId,notification); 94 | notificationManager.cancel(Tag,notificationId); 95 | } 96 | } 97 | 98 | } 99 | -------------------------------------------------------------------------------- /app/src/main/java/com/bonait/bnframework/common/notification/MainNotification.java: -------------------------------------------------------------------------------- 1 | package com.bonait.bnframework.common.notification; 2 | 3 | import android.app.NotificationChannel; 4 | import android.app.NotificationChannelGroup; 5 | import android.app.NotificationManager; 6 | import android.content.Context; 7 | import android.os.Build; 8 | import android.support.annotation.RequiresApi; 9 | 10 | 11 | /** 12 | * Created by LY on 2019/4/22. 13 | * 初始化notification,针对Android8.0以上创建消息渠道组和消息渠道 14 | */ 15 | public class MainNotification { 16 | 17 | public static final String GROUP_DOWNLOAD_ID = "group_download_id"; 18 | public static final String GROUP_PUSH_MESSAGE_ID = "group_push_message_id"; 19 | 20 | public static final String CHANNEL_DOWNLOADING_ID = "channel_downloading_id"; 21 | public static final String CHANNEL_DOWNLOAD_COMPLETE_ID = "channel_download_complete_id"; 22 | public static final String CHANNEL_MESSAGE_ID = "channel_message_id"; 23 | 24 | /** 25 | * 初始化Notification 消息通知渠道 26 | */ 27 | public static void initNotificationChannel(Context context) { 28 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { 29 | // 创建渠道组 30 | createNotificationGroup(context, GROUP_DOWNLOAD_ID, "下载消息"); 31 | createNotificationGroup(context, GROUP_PUSH_MESSAGE_ID, "推送消息"); 32 | 33 | // 创建渠道 34 | // 下载完成通知栏 35 | createNotificationChannel(context, 36 | GROUP_DOWNLOAD_ID, 37 | CHANNEL_DOWNLOAD_COMPLETE_ID, 38 | "下载完成通知栏", 39 | NotificationManager.IMPORTANCE_MAX); 40 | 41 | // 下载通知栏 42 | createNotificationChannel(context, 43 | GROUP_DOWNLOAD_ID, 44 | CHANNEL_DOWNLOADING_ID, 45 | "下载通知栏", 46 | NotificationManager.IMPORTANCE_LOW); 47 | 48 | // 常规通知栏 49 | createNotificationChannel(context, 50 | GROUP_PUSH_MESSAGE_ID, 51 | CHANNEL_MESSAGE_ID, 52 | "常规通知栏", 53 | NotificationManager.IMPORTANCE_MAX); 54 | 55 | } 56 | } 57 | 58 | /** 59 | * 创建消息渠道组 60 | */ 61 | @RequiresApi(api = Build.VERSION_CODES.O) 62 | public static void createNotificationGroup(Context context, String groupId, String groupName) { 63 | NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); 64 | NotificationChannelGroup group = new NotificationChannelGroup(groupId, groupName); 65 | if (notificationManager != null) { 66 | notificationManager.createNotificationChannelGroup(group); 67 | } 68 | } 69 | 70 | /** 71 | * 创建消息渠道,并分配到指定组下。 72 | */ 73 | @RequiresApi(api = Build.VERSION_CODES.O) 74 | public static void createNotificationChannel(Context context, String groupId, String channelId, String channelName, int importance) { 75 | NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); 76 | NotificationChannel channel = new NotificationChannel(channelId, channelName, importance); 77 | channel.canShowBadge(); 78 | //在创建通知渠道前,指定渠道组 id 79 | channel.setGroup(groupId); 80 | if (notificationManager != null) { 81 | notificationManager.createNotificationChannel(channel); 82 | } 83 | } 84 | 85 | } 86 | -------------------------------------------------------------------------------- /app/src/main/java/com/bonait/bnframework/common/utils/AlertDialogUtils.java: -------------------------------------------------------------------------------- 1 | package com.bonait.bnframework.common.utils; 2 | 3 | import android.content.Context; 4 | 5 | import com.qmuiteam.qmui.widget.dialog.QMUIDialog; 6 | import com.qmuiteam.qmui.widget.dialog.QMUIDialogAction; 7 | 8 | /** 9 | * Created by LY on 2019/3/25. 10 | */ 11 | public class AlertDialogUtils { 12 | 13 | // 定义对话框主题样式 14 | public static final int mCurrentDialogStyle = com.qmuiteam.qmui.R.style.QMUI_Dialog; 15 | 16 | /** 17 | * 对话框,只有确定按钮 18 | * */ 19 | public static void showDialog(Context context,String title,String message) { 20 | new QMUIDialog.MessageDialogBuilder(context) 21 | .setCancelable(false) 22 | .setTitle(title) 23 | .setMessage(message) 24 | .addAction("确定", new QMUIDialogAction.ActionListener() { 25 | @Override 26 | public void onClick(QMUIDialog dialog, int index) { 27 | dialog.dismiss(); 28 | } 29 | }) 30 | .create(mCurrentDialogStyle).show(); 31 | } 32 | 33 | /** 34 | * 对话框,只有确定按钮,自定义确定按钮文本 35 | * */ 36 | public static void showDialog(Context context, String title, String message,String ok) { 37 | new QMUIDialog.MessageDialogBuilder(context) 38 | .setCancelable(false) 39 | .setTitle(title) 40 | .setMessage(message) 41 | .addAction(ok, new QMUIDialogAction.ActionListener() { 42 | @Override 43 | public void onClick(QMUIDialog dialog, int index) { 44 | dialog.dismiss(); 45 | } 46 | }) 47 | .create(mCurrentDialogStyle).show(); 48 | } 49 | 50 | /** 51 | * 对话框,有取消确定按钮 52 | * */ 53 | public static void showDialog(Context context, String title, String message, QMUIDialogAction.ActionListener onClickListener) { 54 | new QMUIDialog.MessageDialogBuilder(context) 55 | .setCancelable(false) 56 | .setTitle(title) 57 | .setMessage(message) 58 | .addAction("取消", new QMUIDialogAction.ActionListener() { 59 | @Override 60 | public void onClick(QMUIDialog dialog, int index) { 61 | dialog.dismiss(); 62 | } 63 | }) 64 | .addAction("确定", onClickListener) 65 | .create(mCurrentDialogStyle).show(); 66 | } 67 | 68 | /** 69 | * 对话框,自定义确定按钮 70 | * */ 71 | public static void showDialog(Context context, String title, String message,String ok, QMUIDialogAction.ActionListener onClickListener) { 72 | new QMUIDialog.MessageDialogBuilder(context) 73 | .setCancelable(false) 74 | .setTitle(title) 75 | .setMessage(message) 76 | .addAction("取消", new QMUIDialogAction.ActionListener() { 77 | @Override 78 | public void onClick(QMUIDialog dialog, int index) { 79 | dialog.dismiss(); 80 | } 81 | }) 82 | .addAction(ok, onClickListener) 83 | .create(mCurrentDialogStyle).show(); 84 | } 85 | 86 | /** 87 | * 对话框,带红色按钮 88 | * */ 89 | public static void showRedButtonDialog(Context context, String title, String message,String ok, QMUIDialogAction.ActionListener onClickListener) { 90 | new QMUIDialog.MessageDialogBuilder(context) 91 | .setCancelable(false) 92 | .setTitle(title) 93 | .setMessage(message) 94 | .addAction("取消", new QMUIDialogAction.ActionListener() { 95 | @Override 96 | public void onClick(QMUIDialog dialog, int index) { 97 | dialog.dismiss(); 98 | } 99 | }) 100 | .addAction(0, ok, QMUIDialogAction.ACTION_PROP_NEGATIVE, onClickListener) 101 | .create(mCurrentDialogStyle).show(); 102 | } 103 | 104 | } 105 | -------------------------------------------------------------------------------- /app/src/main/java/com/bonait/bnframework/common/utils/AppUtils.java: -------------------------------------------------------------------------------- 1 | package com.bonait.bnframework.common.utils; 2 | 3 | import android.content.Context; 4 | import android.content.pm.ApplicationInfo; 5 | import android.content.pm.PackageInfo; 6 | import android.content.pm.PackageManager; 7 | 8 | import org.apache.commons.codec.binary.Base64; 9 | 10 | import java.nio.charset.StandardCharsets; 11 | import java.security.MessageDigest; 12 | 13 | /** 14 | * Created by LY on 2019/3/21. 15 | * App版本信息工具类 16 | */ 17 | public class AppUtils { 18 | /** 19 | * 获取版本名称 20 | * 21 | * @param context 上下文 22 | * 23 | * @return 版本名称 24 | */ 25 | public static String getVersionName(Context context) { 26 | 27 | //获取包管理器 28 | PackageManager pm = context.getPackageManager(); 29 | //获取包信息 30 | try { 31 | PackageInfo packageInfo = pm.getPackageInfo(context.getPackageName(), 0); 32 | //返回版本号 33 | return packageInfo.versionName; 34 | } catch (PackageManager.NameNotFoundException e) { 35 | e.printStackTrace(); 36 | } 37 | 38 | return null; 39 | 40 | } 41 | 42 | /** 43 | * 获取版本号 44 | * 45 | * @param context 上下文 46 | * 47 | * @return 版本号 48 | */ 49 | public static int getVersionCode(Context context) { 50 | 51 | //获取包管理器 52 | PackageManager pm = context.getPackageManager(); 53 | //获取包信息 54 | try { 55 | PackageInfo packageInfo = pm.getPackageInfo(context.getPackageName(), 0); 56 | //返回版本号 57 | return packageInfo.versionCode; 58 | } catch (PackageManager.NameNotFoundException e) { 59 | e.printStackTrace(); 60 | } 61 | 62 | return 0; 63 | 64 | } 65 | 66 | /** 67 | * 获取App的名称 68 | * 69 | * @param context 上下文 70 | * 71 | * @return 名称 72 | */ 73 | public static String getAppName(Context context) { 74 | PackageManager pm = context.getPackageManager(); 75 | //获取包信息 76 | try { 77 | PackageInfo packageInfo = pm.getPackageInfo(context.getPackageName(), 0); 78 | //获取应用 信息 79 | ApplicationInfo applicationInfo = packageInfo.applicationInfo; 80 | //获取albelRes 81 | int labelRes = applicationInfo.labelRes; 82 | //返回App的名称 83 | return context.getResources().getString(labelRes); 84 | } catch (PackageManager.NameNotFoundException e) { 85 | e.printStackTrace(); 86 | } 87 | 88 | return null; 89 | } 90 | 91 | /** 92 | * 密码加密,使用SHA-256加密 93 | * 94 | * @param inputStr 密码 95 | * 96 | * @return 加密 97 | */ 98 | public static synchronized String encryptSha256(String inputStr) { 99 | try { 100 | MessageDigest md = MessageDigest.getInstance("SHA-256"); 101 | byte digest[] = md.digest(inputStr.getBytes(StandardCharsets.UTF_8)); 102 | return new String(Base64.encodeBase64(digest)); 103 | } catch (Exception e) { 104 | return null; 105 | } 106 | } 107 | 108 | } 109 | -------------------------------------------------------------------------------- /app/src/main/java/com/bonait/bnframework/common/utils/Des3Utils.java: -------------------------------------------------------------------------------- 1 | package com.bonait.bnframework.common.utils; 2 | 3 | 4 | import android.text.TextUtils; 5 | import android.util.Base64; 6 | 7 | import java.security.Key; 8 | 9 | import javax.crypto.Cipher; 10 | import javax.crypto.SecretKeyFactory; 11 | import javax.crypto.spec.DESedeKeySpec; 12 | import javax.crypto.spec.IvParameterSpec; 13 | 14 | /** 15 | * Created by LY on 2019/4/10. 16 | * 3DES 加密/解密 17 | */ 18 | public class Des3Utils { 19 | 20 | // 密钥 长度等于24,且不得小于24 21 | private final static String secretKey = "CW0Y&S7l1BVU2zwKop@syT92"; 22 | // 向量 可有可无 终端后台也要约定 23 | private final static String iv = "01234567"; 24 | 25 | /** 26 | * 3DES转变 27 | *

法算法名称/加密模式/填充方式

28 | *

加密模式有:电子密码本模式ECB、加密块链模式CBC、加密反馈模式CFB、输出反馈模式OFB

29 | *

填充方式有:NoPadding、ZerosPadding、PKCS5Padding

30 | */ 31 | private static String TripleDES_Transformation = "desede/CBC/PKCS5Padding"; 32 | 33 | // 加密算法类型 34 | private static final String TripleDES_Algorithm = "desede"; 35 | 36 | // 加解密统一使用的编码方式 37 | private final static String encoding = "utf-8"; 38 | 39 | /** 40 | * 3DES加密 41 | * 42 | * @param plainText 普通文本 43 | * @return 加密Str 44 | */ 45 | public static String encode(String plainText) { 46 | if (TextUtils.isEmpty(plainText)) { 47 | return null; 48 | } 49 | 50 | try { 51 | DESedeKeySpec spec = new DESedeKeySpec(secretKey.getBytes()); 52 | SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(TripleDES_Algorithm); 53 | Key desKey = keyFactory.generateSecret(spec); 54 | 55 | Cipher cipher = Cipher.getInstance(TripleDES_Transformation); 56 | IvParameterSpec ips = new IvParameterSpec(iv.getBytes()); 57 | cipher.init(Cipher.ENCRYPT_MODE, desKey, ips); 58 | 59 | byte[] encryptData = cipher.doFinal(plainText.getBytes(encoding)); 60 | 61 | return Base64.encodeToString(encryptData, Base64.DEFAULT); 62 | 63 | }catch (Exception e ) { 64 | e.printStackTrace(); 65 | return null; 66 | } 67 | } 68 | 69 | /** 70 | * 3DES解密 71 | * 72 | * @param encryptText 加密文本 73 | * @return 解密Str 74 | */ 75 | public static String decode(String encryptText) { 76 | if (TextUtils.isEmpty(encryptText)) { 77 | return null; 78 | } 79 | 80 | try { 81 | DESedeKeySpec spec = new DESedeKeySpec(secretKey.getBytes()); 82 | SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(TripleDES_Algorithm); 83 | Key desKey = keyFactory.generateSecret(spec); 84 | 85 | Cipher cipher = Cipher.getInstance(TripleDES_Transformation); 86 | IvParameterSpec ips = new IvParameterSpec(iv.getBytes()); 87 | cipher.init(Cipher.DECRYPT_MODE, desKey, ips); 88 | 89 | byte[] decryptData = cipher.doFinal(Base64.decode(encryptText, Base64.DEFAULT)); 90 | 91 | return new String(decryptData, encoding); 92 | 93 | } catch (Exception e) { 94 | e.printStackTrace(); 95 | return null; 96 | } 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /app/src/main/java/com/bonait/bnframework/common/utils/KeyboardToolUtils.java: -------------------------------------------------------------------------------- 1 | package com.bonait.bnframework.common.utils; 2 | 3 | import android.app.Activity; 4 | import android.content.Context; 5 | import android.view.View; 6 | import android.view.inputmethod.InputMethodManager; 7 | import android.widget.EditText; 8 | 9 | /** 10 | * Created by LY on 2019/3/28. 11 | * 软键盘工具类 12 | */ 13 | public class KeyboardToolUtils { 14 | /** 15 | * 避免输入法面板遮挡 16 | *

在manifest.xml中activity中设置

17 | *

android:windowSoftInputMode="stateVisible|adjustResize"

18 | */ 19 | 20 | /** 21 | * 动态隐藏软键盘 22 | * 23 | * @param activity activity 24 | */ 25 | public static void hideSoftInput(Activity activity) { 26 | View view = activity.getWindow().peekDecorView(); 27 | if (view != null) { 28 | InputMethodManager inputManger = (InputMethodManager) activity 29 | .getSystemService(Context.INPUT_METHOD_SERVICE); 30 | if (inputManger != null) { 31 | inputManger.hideSoftInputFromWindow(view.getWindowToken(), 0); 32 | } 33 | } 34 | } 35 | 36 | /** 37 | * 点击隐藏软键盘 38 | * 39 | * @param activity 40 | * @param view 41 | */ 42 | public static void hideKeyboard(Activity activity, View view) { 43 | InputMethodManager imm = (InputMethodManager) activity.getSystemService(Context.INPUT_METHOD_SERVICE); 44 | if (imm != null) { 45 | imm.hideSoftInputFromWindow(view.getWindowToken(), 0); 46 | } 47 | } 48 | 49 | /** 50 | * 动态隐藏软键盘 51 | * 52 | * @param context 上下文 53 | * @param edit 输入框 54 | */ 55 | public static void hideSoftInput(Context context, EditText edit) { 56 | edit.clearFocus(); 57 | InputMethodManager inputManger = (InputMethodManager) context 58 | .getSystemService(Context.INPUT_METHOD_SERVICE); 59 | if (inputManger != null) { 60 | inputManger.hideSoftInputFromWindow(edit.getWindowToken(), 0); 61 | } 62 | } 63 | 64 | /** 65 | * 点击屏幕空白区域隐藏软键盘(方法1) 66 | *

在onTouch中处理,未获焦点则隐藏

67 | *

参照以下注释代码

68 | */ 69 | public static void clickBlankArea2HideSoftInput0() { 70 | /* 71 | @Override 72 | public boolean onTouchEvent (MotionEvent event){ 73 | if (null != this.getCurrentFocus()) { 74 | InputMethodManager mInputMethodManager = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE); 75 | return mInputMethodManager.hideSoftInputFromWindow(this.getCurrentFocus().getWindowToken(), 0); 76 | } 77 | return super.onTouchEvent(event); 78 | } 79 | */ 80 | } 81 | 82 | /** 83 | * 点击屏幕空白区域隐藏软键盘(方法2) 84 | *

根据EditText所在坐标和用户点击的坐标相对比,来判断是否隐藏键盘

85 | *

需重写dispatchTouchEvent

86 | *

参照以下注释代码

87 | */ 88 | public static void clickBlankArea2HideSoftInput1() { 89 | /* 90 | @Override 91 | public boolean dispatchTouchEvent(MotionEvent ev) { 92 | if (ev.getAction() == MotionEvent.ACTION_DOWN) { 93 | View v = getCurrentFocus(); 94 | if (isShouldHideKeyboard(v, ev)) { 95 | hideKeyboard(v.getWindowToken()); 96 | } 97 | } 98 | return super.dispatchTouchEvent(ev); 99 | } 100 | // 根据EditText所在坐标和用户点击的坐标相对比,来判断是否隐藏键盘 101 | private boolean isShouldHideKeyboard(View v, MotionEvent event) { 102 | if (v != null && (v instanceof EditText)) { 103 | int[] l = {0, 0}; 104 | v.getLocationInWindow(l); 105 | int left = l[0], 106 | top = l[1], 107 | bottom = top + v.getHeight(), 108 | right = left + v.getWidth(); 109 | return !(event.getX() > left && event.getX() < right 110 | && event.getY() > top && event.getY() < bottom); 111 | } 112 | return false; 113 | } 114 | // 获取InputMethodManager,隐藏软键盘 115 | private void hideKeyboard(IBinder token) { 116 | if (token != null) { 117 | InputMethodManager im = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); 118 | im.hideSoftInputFromWindow(token, InputMethodManager.HIDE_NOT_ALWAYS); 119 | } 120 | } 121 | */ 122 | } 123 | 124 | /** 125 | * 动态显示软键盘 126 | * 127 | * @param context 上下文 128 | * @param edit 输入框 129 | */ 130 | public static void showSoftInput(Context context, EditText edit) { 131 | edit.setFocusable(true); 132 | edit.setFocusableInTouchMode(true); 133 | edit.requestFocus(); 134 | InputMethodManager inputManager = (InputMethodManager) context 135 | .getSystemService(Context.INPUT_METHOD_SERVICE); 136 | if (inputManager != null) { 137 | inputManager.showSoftInput(edit, 0); 138 | } 139 | } 140 | 141 | /** 142 | * 切换键盘显示与否状态 143 | * 144 | * @param context 上下文 145 | * @param edit 输入框 146 | */ 147 | public static void toggleSoftInput(Context context, EditText edit) { 148 | edit.setFocusable(true); 149 | edit.setFocusableInTouchMode(true); 150 | edit.requestFocus(); 151 | InputMethodManager inputManager = (InputMethodManager) context 152 | .getSystemService(Context.INPUT_METHOD_SERVICE); 153 | if (inputManager != null) { 154 | inputManager.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0); 155 | } 156 | } 157 | } 158 | -------------------------------------------------------------------------------- /app/src/main/java/com/bonait/bnframework/common/utils/NetworkUtils.java: -------------------------------------------------------------------------------- 1 | package com.bonait.bnframework.common.utils; 2 | 3 | import android.content.Context; 4 | import android.net.ConnectivityManager; 5 | import android.net.NetworkCapabilities; 6 | import android.net.NetworkInfo; 7 | import android.os.Build; 8 | 9 | /** 10 | * Created by LY on 2019/1/4. 11 | */ 12 | public class NetworkUtils { 13 | 14 | /** 15 | * 检测当的网络(WLAN、4G/3G/2G)状态,兼容Android 6.0以下 16 | * @param context Context 17 | * @return true 表示网络可用 18 | */ 19 | public static boolean isNetworkConnected(Context context) { 20 | boolean result = false; 21 | try { 22 | ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); 23 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { 24 | if (cm != null) { 25 | NetworkCapabilities capabilities = cm.getNetworkCapabilities(cm.getActiveNetwork()); 26 | if (capabilities != null) { 27 | if (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) { 28 | result = true; 29 | } else if (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) { 30 | result = true; 31 | } 32 | } 33 | } 34 | } else { 35 | if (cm != null) { 36 | NetworkInfo activeNetwork = cm.getActiveNetworkInfo(); 37 | if (activeNetwork != null) { 38 | // connected to the internet 39 | if (activeNetwork.getType() == ConnectivityManager.TYPE_WIFI) { 40 | result = true; 41 | } else if (activeNetwork.getType() == ConnectivityManager.TYPE_MOBILE) { 42 | result = true; 43 | } 44 | } 45 | } 46 | } 47 | 48 | } catch (Exception e) { 49 | return false; 50 | } 51 | 52 | return result; 53 | } 54 | 55 | /** 56 | * 判断是否是移动网络连接 57 | * */ 58 | public static boolean isActiveNetworkMobile(Context context) { 59 | ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); 60 | if (connectivityManager != null) { 61 | NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo(); 62 | return networkInfo != null && networkInfo.getType() == ConnectivityManager.TYPE_MOBILE; 63 | } 64 | return false; 65 | } 66 | 67 | /** 68 | * 判断是否是wifi 69 | * */ 70 | public static boolean isActiveNetworkWifi(Context context) { 71 | ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); 72 | if (connectivityManager != null) { 73 | NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo(); 74 | return networkInfo != null && networkInfo.getType() == ConnectivityManager.TYPE_WIFI; 75 | } 76 | return false; 77 | } 78 | 79 | /** 80 | * @deprecated 请先使用 {@link NetworkUtils#isNetworkConnected(Context)} 方法 81 | * 82 | * 检测当的网络(WLAN、4G/3G/2G)状态 83 | * 84 | * @param context Context 85 | * @return true 表示网络可用 86 | */ 87 | @Deprecated 88 | public static boolean checkNet(Context context) { 89 | 90 | try { 91 | ConnectivityManager connectivity = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); 92 | if (connectivity != null) { 93 | 94 | NetworkInfo info = connectivity.getActiveNetworkInfo(); 95 | if (info != null && info.isConnected()) { 96 | 97 | /*if (info.getState() == NetworkInfo.State.CONNECTED) { 98 | return true; 99 | }*/ 100 | NetworkCapabilities networkCapabilities = connectivity.getNetworkCapabilities(connectivity.getActiveNetwork()); 101 | return networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED); 102 | } 103 | } 104 | } catch (Exception e) { 105 | return false; 106 | } 107 | return false; 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /app/src/main/java/com/bonait/bnframework/common/utils/PreferenceUtils.java: -------------------------------------------------------------------------------- 1 | package com.bonait.bnframework.common.utils; 2 | 3 | import android.content.Context; 4 | import android.content.SharedPreferences; 5 | 6 | /** 7 | * Created by LY on 2019/3/21. 8 | */ 9 | public class PreferenceUtils { 10 | private static SharedPreferences sharedPreferences; 11 | 12 | /** 13 | * 初始化SharedPreferences 14 | * */ 15 | public static void initPreference(Context context,String name,int mode) { 16 | if (sharedPreferences == null) { 17 | sharedPreferences = context.getSharedPreferences(name, mode); 18 | } 19 | } 20 | 21 | /** 22 | * 存String 23 | * @param key 键 24 | * @param value 值 25 | */ 26 | public static void setString(String key, String value) { 27 | sharedPreferences.edit().putString(key,value).apply(); 28 | } 29 | 30 | /** 31 | * 取String 32 | * @param key 键 33 | * @param devalue 默认值 34 | * @return String 35 | */ 36 | public static String getString(String key, String devalue) { 37 | return sharedPreferences.getString(key,devalue); 38 | } 39 | 40 | /** 41 | * 存Float 42 | * @param key 键 43 | * @param value 值 44 | */ 45 | public static void setFloat(String key, float value) { 46 | sharedPreferences.edit().putFloat(key,value).apply(); 47 | } 48 | 49 | /** 50 | * 取Float 51 | * @param key 键 52 | * @param devalue 默认值 53 | * @return Float 54 | */ 55 | public static Float getFloat(String key, float devalue){ 56 | return sharedPreferences.getFloat(key,devalue); 57 | } 58 | 59 | /** 60 | * 存boolean 61 | * @param key 键 62 | * @param value 值 63 | */ 64 | public static void setBoolean(String key, boolean value) { 65 | sharedPreferences.edit().putBoolean(key,value).apply(); 66 | } 67 | 68 | /** 69 | * 取boolean 70 | * @param key 键 71 | * @param defValue 默认值 72 | * @return Boolean 73 | */ 74 | public static boolean getBoolean(String key, boolean defValue) { 75 | return sharedPreferences.getBoolean(key,defValue); 76 | } 77 | 78 | /** 79 | * 存int 80 | * @param key 键 81 | * @param value 值 82 | */ 83 | public static void setInt(String key, int value) { 84 | sharedPreferences.edit().putInt(key,value).apply(); 85 | } 86 | 87 | /** 88 | * 存int 89 | * @param key 键 90 | * @param value 值 91 | */ 92 | public static void setInt(String key, Integer value) { 93 | sharedPreferences.edit().putInt(key,(Integer) value).apply(); 94 | } 95 | 96 | /** 97 | * 取int 98 | * @param key 键 99 | * @param defValue 默认值 100 | * @return Int 101 | */ 102 | public static int getInt(String key, int defValue) { 103 | return sharedPreferences.getInt(key,defValue); 104 | } 105 | 106 | /** 107 | * 存Long 108 | * @param key 键 109 | * @param value 值 110 | */ 111 | public static void setLong(String key, int value) { 112 | sharedPreferences.edit().putLong(key,value).apply(); 113 | } 114 | 115 | /** 116 | * 取Long 117 | * @param key 键 118 | * @param defValue 默认值 119 | * @return Long 120 | */ 121 | public static Long getLong(String key, int defValue) { 122 | return sharedPreferences.getLong(key,defValue); 123 | } 124 | 125 | /** 126 | * 清空一个 127 | * @param key 键 128 | */ 129 | public static void remove(String key) { 130 | sharedPreferences.edit().remove(key).apply(); 131 | } 132 | 133 | /** 134 | * 清空所有 135 | */ 136 | public static void removeAll() { 137 | sharedPreferences.edit().clear().apply(); 138 | } 139 | } 140 | -------------------------------------------------------------------------------- /app/src/main/java/com/bonait/bnframework/common/utils/UpdateAppUtils.java: -------------------------------------------------------------------------------- 1 | package com.bonait.bnframework.common.utils; 2 | 3 | import android.content.Context; 4 | import android.content.Intent; 5 | import android.net.Uri; 6 | import android.os.Build; 7 | import android.support.v4.content.FileProvider; 8 | 9 | import com.bonait.bnframework.common.constant.Constants; 10 | import com.bonait.bnframework.common.http.callback.files.FileProgressDialogCallBack; 11 | import com.bonait.bnframework.common.http.callback.json.JsonDialogCallback; 12 | import com.bonait.bnframework.modules.mine.model.UpdateAppPo; 13 | import com.lzy.okgo.OkGo; 14 | import com.lzy.okgo.model.Response; 15 | import com.qmuiteam.qmui.widget.dialog.QMUIDialog; 16 | import com.qmuiteam.qmui.widget.dialog.QMUIDialogAction; 17 | 18 | import java.io.File; 19 | 20 | /** 21 | * Created by LY on 2019/4/1. 22 | */ 23 | public class UpdateAppUtils { 24 | 25 | /** 26 | * apk下载地址 27 | */ 28 | private static String downloadUrl = ""; 29 | 30 | /** 31 | * 获取服务器apk下载地址ID 32 | */ 33 | private static String serviceApkId = ""; 34 | /** 35 | * 当前版本号 36 | */ 37 | private static int myVersionCode = 0; 38 | /** 39 | * 服务器的版本号码 40 | */ 41 | private static int serviceVersionCode = 0; 42 | /** 43 | * 服务器的版本号名称 44 | */ 45 | private static String serviceVersionName = ""; 46 | /** 47 | * 更新说明 48 | */ 49 | private static String description = ""; 50 | 51 | /** 52 | * 更新APP版本入口 53 | */ 54 | public static void updateApp(Context context) { 55 | //获取当前app版本号 56 | myVersionCode = AppUtils.getVersionCode(context); 57 | //获取json转成Gson,并获取版本等信息 58 | doPost(context); 59 | } 60 | 61 | /** 62 | * 请求后台服务器,检查apk版本 63 | */ 64 | private static void doPost(final Context context) { 65 | String getNewVersionUrl = Constants.SERVICE_IP + "/iandroid/appVersionAction!getNewVersion.do"; 66 | OkGo.post(getNewVersionUrl) 67 | .tag(context) 68 | .execute(new JsonDialogCallback(context) { 69 | @Override 70 | public void onSuccess(Response response) { 71 | UpdateAppPo updateAppPo = response.body(); 72 | if (updateAppPo != null) { 73 | serviceVersionCode = updateAppPo.getVersion(); 74 | description = updateAppPo.getDescription(); 75 | serviceApkId = updateAppPo.getApkId(); 76 | //获取apk下载地址 77 | String url = Constants.SERVICE_IP + "/file-download?fileId="; 78 | downloadUrl = url + serviceApkId; 79 | // 判断Apk是否是最新版本 80 | if (myVersionCode < serviceVersionCode) { 81 | showUpdateDialog(context); 82 | } else { 83 | ToastUtils.info("当前版本已是最新版本"); 84 | } 85 | 86 | } 87 | } 88 | }); 89 | } 90 | 91 | /** 92 | * 弹出下载对话框,里面有一些更新版本的信息 93 | */ 94 | private static void showUpdateDialog(final Context context) { 95 | new QMUIDialog.MessageDialogBuilder(context) 96 | .setCancelable(false) 97 | .setTitle("发现新版本") 98 | .setMessage(description) 99 | .addAction("取消", new QMUIDialogAction.ActionListener() { 100 | @Override 101 | public void onClick(QMUIDialog dialog, int index) { 102 | dialog.dismiss(); 103 | } 104 | }) 105 | .addAction("去更新", new QMUIDialogAction.ActionListener() { 106 | @Override 107 | public void onClick(QMUIDialog dialog, int index) { 108 | downloadApk(context); 109 | dialog.dismiss(); 110 | } 111 | }) 112 | .create(AlertDialogUtils.mCurrentDialogStyle) 113 | .show(); 114 | } 115 | 116 | private static void downloadApk(final Context context) { 117 | OkGo.get(downloadUrl) 118 | .tag(context) 119 | .execute(new FileProgressDialogCallBack(context) { 120 | @Override 121 | public void onSuccess(Response response) { 122 | File file = response.body(); 123 | String absolutePath = file.getAbsolutePath(); 124 | installApk(context, absolutePath); 125 | } 126 | }); 127 | } 128 | 129 | /** 130 | * 跳转apk安装界面 131 | */ 132 | public static void installApk(Context context, String filePath) { 133 | Intent i = new Intent(Intent.ACTION_VIEW); 134 | File file = new File(filePath); 135 | if (file.length() > 0 && file.exists() && file.isFile()) { 136 | //判断是否是AndroidN以及更高的版本 137 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { 138 | i.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); 139 | Uri contentUri = FileProvider.getUriForFile(context, context.getPackageName() + ".fileProvider", file); 140 | i.setDataAndType(contentUri, "application/vnd.android.package-archive"); 141 | } else { 142 | i.setDataAndType(Uri.fromFile(file), "application/vnd.android.package-archive"); 143 | i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 144 | } 145 | context.startActivity(i); 146 | } 147 | } 148 | } 149 | -------------------------------------------------------------------------------- /app/src/main/java/com/bonait/bnframework/common/view/ClearEditTextView.java: -------------------------------------------------------------------------------- 1 | package com.bonait.bnframework.common.view; 2 | 3 | import android.annotation.SuppressLint; 4 | import android.content.Context; 5 | import android.graphics.Rect; 6 | import android.graphics.drawable.Drawable; 7 | import android.support.v7.widget.AppCompatEditText; 8 | import android.text.Editable; 9 | import android.text.TextWatcher; 10 | import android.util.AttributeSet; 11 | import android.view.MotionEvent; 12 | import android.view.View; 13 | import android.view.animation.Animation; 14 | import android.view.animation.CycleInterpolator; 15 | import android.view.animation.TranslateAnimation; 16 | 17 | import com.bonait.bnframework.R; 18 | 19 | /** 20 | * Created by LY on 2019/4/24. 21 | * 22 | */ 23 | public class ClearEditTextView extends AppCompatEditText implements View.OnFocusChangeListener, TextWatcher { 24 | /** 25 | * 删除按钮的引用 26 | */ 27 | private Drawable mClearDrawable; 28 | /** 29 | * 控件是否有焦点 30 | */ 31 | private boolean hasFocus; 32 | 33 | public ClearEditTextView(Context context) { 34 | this(context,null); 35 | // super(context); 36 | // this.context = context; 37 | // init(); 38 | } 39 | public ClearEditTextView(Context context, AttributeSet attrs){ 40 | //这里构造方法也很重要,不加这个很多属性不能再XML里面定义 41 | this(context, attrs, android.R.attr.editTextStyle); 42 | } 43 | 44 | public ClearEditTextView(Context context, AttributeSet attrs, int defStyle) { 45 | super(context, attrs, defStyle); 46 | init(); 47 | } 48 | private void init() { 49 | 50 | //获取EditText的DrawableRight,假如没有设置我们就使用默认的图片 51 | mClearDrawable = getCompoundDrawables()[2]; 52 | if (mClearDrawable == null) { 53 | mClearDrawable = getResources().getDrawable(R.drawable.delete_selector,null); 54 | } 55 | mClearDrawable.setBounds(0, 0, mClearDrawable.getIntrinsicWidth(), mClearDrawable.getIntrinsicHeight()); 56 | //默认设置隐藏图标 57 | setClearIconVisible(false); 58 | //设置焦点改变的监听 59 | setOnFocusChangeListener(this); 60 | //设置输入框里面内容发生改变的监听 61 | addTextChangedListener(this); 62 | } 63 | 64 | @SuppressLint("ClickableViewAccessibility") 65 | @Override 66 | public boolean onTouchEvent(MotionEvent event) { 67 | 68 | if (mClearDrawable != null && event.getAction() == MotionEvent.ACTION_UP) { 69 | int x = (int) event.getX(); 70 | //判断触摸点是否在水平范围内 71 | boolean isInnerWidth = (x > (getWidth() - getTotalPaddingRight())) && 72 | (x < (getWidth() - getPaddingRight())); 73 | //获取删除图标的边界,返回一个Rect对象 74 | Rect rect = mClearDrawable.getBounds(); 75 | //获取删除图标的高度 76 | int height = rect.height(); 77 | int y = (int) event.getY(); 78 | //计算图标底部到控件底部的距离 79 | int distance = (getHeight() - height) / 2; 80 | //判断触摸点是否在竖直范围内(可能会有点误差) 81 | //触摸点的纵坐标在distance到(distance+图标自身的高度)之内,则视为点中删除图标 82 | boolean isInnerHeight = (y > distance) && (y < (distance + height)); 83 | if (isInnerHeight && isInnerWidth) { 84 | this.setText(""); 85 | } 86 | } 87 | return super.onTouchEvent(event); 88 | } 89 | 90 | /** 91 | * 设置清除图标的显示与隐藏,调用setCompoundDrawables为EditText绘制上去 92 | * 93 | * @param visible 图标是否隐藏 94 | */ 95 | private void setClearIconVisible(boolean visible) { 96 | Drawable right = visible ? mClearDrawable : null; 97 | setCompoundDrawables(getCompoundDrawables()[0], getCompoundDrawables()[1], 98 | right, getCompoundDrawables()[3]); 99 | } 100 | 101 | /** 102 | * 当ClearEditText焦点发生变化的时候,判断里面字符串长度设置清除图标的显示与隐藏 103 | */ 104 | @Override 105 | public void onFocusChange(View v, boolean hasFocus) { 106 | this.hasFocus = hasFocus; 107 | if (hasFocus) { 108 | setClearIconVisible(getText().length() > 0); 109 | } else { 110 | setClearIconVisible(false); 111 | } 112 | } 113 | 114 | /*@Override 115 | protected void onSelectionChanged(int selStart, int selEnd) { 116 | super.onSelectionChanged(selStart, selEnd); 117 | //光标首次获取焦点是在最后面,之后操作就是按照点击的位置移动光标 118 | if (isEnabled() && hasFocus() && hasFocusable()) { 119 | setSelection(selEnd); 120 | } else { 121 | setSelection(getText().length()); 122 | } 123 | }*/ 124 | 125 | /** 126 | * 当输入框里面内容发生变化的时候回调的方法 127 | */ 128 | @Override 129 | public void onTextChanged(CharSequence text, int start, int lengthBefore, int lengthAfter) { 130 | if (hasFocus) { 131 | setClearIconVisible(text.length() > 0); 132 | } 133 | } 134 | 135 | @Override 136 | public void beforeTextChanged(CharSequence s, int start, int count, int after) { 137 | } 138 | 139 | @Override 140 | public void afterTextChanged(Editable s) { 141 | 142 | } 143 | 144 | /** 145 | * 设置晃动动画 146 | */ 147 | public void setShakeAnimation() { 148 | this.setAnimation(shakeAnimation(5)); 149 | } 150 | 151 | /** 152 | * 晃动动画 153 | * 154 | * @param counts 1秒钟晃动多少下 155 | * @return 动画 156 | */ 157 | public static Animation shakeAnimation(int counts) { 158 | Animation translateAnimation = new TranslateAnimation(0, 10, 0, 0); 159 | translateAnimation.setInterpolator(new CycleInterpolator(counts)); 160 | translateAnimation.setDuration(1000); 161 | return translateAnimation; 162 | } 163 | } 164 | -------------------------------------------------------------------------------- /app/src/main/java/com/bonait/bnframework/common/view/QMAutoDialogBuilderView.java: -------------------------------------------------------------------------------- 1 | package com.bonait.bnframework.common.view; 2 | 3 | import android.content.Context; 4 | import android.support.v4.content.ContextCompat; 5 | import android.view.View; 6 | import android.view.ViewGroup; 7 | import android.widget.EditText; 8 | import android.widget.LinearLayout; 9 | import android.widget.ScrollView; 10 | import android.widget.TextView; 11 | 12 | import com.bonait.bnframework.R; 13 | import com.qmuiteam.qmui.util.QMUIDisplayHelper; 14 | import com.qmuiteam.qmui.util.QMUIResHelper; 15 | import com.qmuiteam.qmui.util.QMUIViewHelper; 16 | import com.qmuiteam.qmui.widget.dialog.QMUIDialog; 17 | 18 | /** 19 | * Created by LY on 2019/3/25. 20 | */ 21 | public class QMAutoDialogBuilderView extends QMUIDialog.AutoResizeDialogBuilder { 22 | 23 | private Context mContext; 24 | private EditText mEditText; 25 | 26 | public QMAutoDialogBuilderView(Context context) { 27 | super(context); 28 | mContext = context; 29 | } 30 | 31 | public EditText getEditText() { 32 | return mEditText; 33 | } 34 | 35 | @Override 36 | public View onBuildContent(QMUIDialog dialog, ScrollView parent) { 37 | LinearLayout layout = new LinearLayout(mContext); 38 | layout.setOrientation(LinearLayout.VERTICAL); 39 | layout.setLayoutParams(new ScrollView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)); 40 | int padding = QMUIDisplayHelper.dp2px(mContext, 20); 41 | layout.setPadding(padding, padding, padding, padding); 42 | mEditText = new EditText(mContext); 43 | QMUIViewHelper.setBackgroundKeepingPadding(mEditText, QMUIResHelper.getAttrDrawable(mContext, R.attr.qmui_list_item_bg_with_border_bottom)); 44 | mEditText.setHint("输入框"); 45 | LinearLayout.LayoutParams editTextLP = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, QMUIDisplayHelper.dpToPx(50)); 46 | editTextLP.bottomMargin = QMUIDisplayHelper.dp2px(mContext, 15); 47 | mEditText.setLayoutParams(editTextLP); 48 | layout.addView(mEditText); 49 | TextView textView = new TextView(mContext); 50 | textView.setLineSpacing(QMUIDisplayHelper.dp2px(mContext, 4), 1.0f); 51 | textView.setText("观察聚焦输入框后,键盘升起降下时 dialog 的高度自适应变化。\n\n" + 52 | "QMUI Android 的设计目的是用于辅助快速搭建一个具备基本设计还原效果的 Android 项目," + 53 | "同时利用自身提供的丰富控件及兼容处理,让开发者能专注于业务需求而无需耗费精力在基础代码的设计上。" + 54 | "不管是新项目的创建,或是已有项目的维护,均可使开发效率和项目质量得到大幅度提升。"); 55 | textView.setTextColor(ContextCompat.getColor(mContext, R.color.app_color_description)); 56 | textView.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)); 57 | layout.addView(textView); 58 | return layout; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /app/src/main/java/com/bonait/bnframework/manager/ActivityLifecycleManager.java: -------------------------------------------------------------------------------- 1 | package com.bonait.bnframework.manager; 2 | 3 | import android.app.Activity; 4 | import android.app.Application; 5 | import android.content.pm.ActivityInfo; 6 | import android.os.Bundle; 7 | 8 | import java.util.Collections; 9 | import java.util.LinkedList; 10 | import java.util.List; 11 | 12 | /** 13 | * Created by LY on 2019/4/3. 14 | */ 15 | public class ActivityLifecycleManager implements Application.ActivityLifecycleCallbacks { 16 | 17 | /** 18 | * 维护Activity 的list 19 | */ 20 | private static List activityList = Collections.synchronizedList(new LinkedList()); 21 | //private List activityList = new LinkedList(); 22 | 23 | 24 | /*单例模式静态内部类*/ 25 | private static class SingletonHolder{ 26 | private static ActivityLifecycleManager instance = new ActivityLifecycleManager(); 27 | } 28 | private ActivityLifecycleManager(){ 29 | } 30 | 31 | public static ActivityLifecycleManager get(){ 32 | return SingletonHolder.instance; 33 | } 34 | 35 | /** 36 | * 开启ActivityLifecycleCallbacks接口回调 37 | */ 38 | public void init(Application application){ 39 | application.registerActivityLifecycleCallbacks(get()); 40 | } 41 | 42 | 43 | 44 | /** 45 | * @param activity 作用说明 :添加一个activity到管理里 46 | */ 47 | public void pushActivity(Activity activity) { 48 | activityList.add(activity); 49 | } 50 | 51 | /** 52 | * @param activity 作用说明 :删除一个activity在管理里 53 | */ 54 | public void popActivity(Activity activity) { 55 | activityList.remove(activity); 56 | } 57 | 58 | /** 59 | * get current Activity 获取当前Activity(栈中最后一个压入的) 60 | */ 61 | public Activity currentActivity() { 62 | if (activityList == null|| activityList.isEmpty()) { 63 | return null; 64 | } 65 | return activityList.get(activityList.size()-1); 66 | } 67 | 68 | /** 69 | * 结束当前Activity(栈中最后一个压入的) 70 | */ 71 | public void finishCurrentActivity() { 72 | if (activityList == null|| activityList.isEmpty()) { 73 | return; 74 | } 75 | Activity activity = activityList.get(activityList.size()-1); 76 | finishActivity(activity); 77 | } 78 | 79 | /** 80 | * 结束指定的Activity 81 | */ 82 | public void finishActivity(Activity activity) { 83 | if (activityList == null|| activityList.isEmpty()) { 84 | return; 85 | } 86 | if (activity != null) { 87 | activityList.remove(activity); 88 | activity.finish(); 89 | activity = null; 90 | } 91 | } 92 | 93 | /** 94 | * 结束指定类名的Activity 95 | */ 96 | public void finishActivity(Class cls) { 97 | if (activityList == null|| activityList.isEmpty()) { 98 | return; 99 | } 100 | for (Activity activity : activityList) { 101 | if (activity.getClass().equals(cls)) { 102 | finishActivity(activity); 103 | } 104 | } 105 | } 106 | 107 | /** 108 | * 按照指定类名找到activity 109 | * 110 | */ 111 | public Activity findActivity(Class cls) { 112 | Activity targetActivity = null; 113 | if (activityList != null) { 114 | for (Activity activity : activityList) { 115 | if (activity.getClass().equals(cls)) { 116 | targetActivity = activity; 117 | break; 118 | } 119 | } 120 | } 121 | return targetActivity; 122 | } 123 | 124 | /** 125 | * @return 作用说明 :获取当前最顶部activity的实例 126 | */ 127 | public Activity getTopActivity() { 128 | Activity mBaseActivity; 129 | synchronized (activityList) { 130 | final int size = activityList.size() - 1; 131 | if (size < 0) { 132 | return null; 133 | } 134 | mBaseActivity = activityList.get(size); 135 | } 136 | return mBaseActivity; 137 | 138 | } 139 | 140 | /** 141 | * @return 作用说明 :获取当前最顶部的acitivity 名字 142 | */ 143 | public String getTopActivityName() { 144 | Activity mBaseActivity; 145 | synchronized (activityList) { 146 | final int size = activityList.size() - 1; 147 | if (size < 0) { 148 | return null; 149 | } 150 | mBaseActivity = activityList.get(size); 151 | } 152 | return mBaseActivity.getClass().getName(); 153 | } 154 | 155 | /** 156 | * 结束所有Activity 157 | */ 158 | public void finishAllActivity() { 159 | if (activityList == null) { 160 | return; 161 | } 162 | for (Activity activity : activityList) { 163 | activity.finish(); 164 | } 165 | activityList.clear(); 166 | } 167 | 168 | /** 169 | * 退出应用程序 170 | */ 171 | public void appExit() { 172 | try { 173 | finishAllActivity(); 174 | System.exit(0); 175 | } catch (Exception e) { 176 | e.getStackTrace(); 177 | } 178 | } 179 | 180 | 181 | @Override 182 | public void onActivityCreated(Activity activity, Bundle savedInstanceState) { 183 | /* 184 | * 监听到 Activity创建事件 将该 Activity 加入list 185 | */ 186 | pushActivity(activity); 187 | // 设置禁止随屏幕旋转界面 188 | activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); 189 | } 190 | 191 | @Override 192 | public void onActivityStarted(Activity activity) { 193 | 194 | } 195 | 196 | @Override 197 | public void onActivityResumed(Activity activity) { 198 | 199 | } 200 | 201 | @Override 202 | public void onActivityPaused(Activity activity) { 203 | 204 | } 205 | 206 | @Override 207 | public void onActivityStopped(Activity activity) { 208 | 209 | } 210 | 211 | @Override 212 | public void onActivitySaveInstanceState(Activity activity, Bundle outState) { 213 | 214 | } 215 | 216 | @Override 217 | public void onActivityDestroyed(Activity activity) { 218 | if (null==activityList||activityList.isEmpty()) { 219 | return; 220 | } 221 | if (activityList.contains(activity)) { 222 | /* 223 | * 监听到 Activity销毁事件 将该Activity 从list中移除 224 | */ 225 | popActivity(activity); 226 | } 227 | 228 | //横竖屏切换或配置改变时, Activity 会被重新创建实例, 但 Bundle 中的基础数据会被保存下来,移除该数据是为了保证重新创建的实例可以正常工作 229 | // 暂时没用到保存toolbar 230 | //activity.getIntent().removeExtra("isInitToolbar"); 231 | } 232 | } 233 | -------------------------------------------------------------------------------- /app/src/main/java/com/bonait/bnframework/modules/home/activity/BottomNavigation2Activity.java: -------------------------------------------------------------------------------- 1 | package com.bonait.bnframework.modules.home.activity; 2 | 3 | import android.os.Bundle; 4 | import android.support.annotation.NonNull; 5 | import android.support.design.widget.BottomNavigationView; 6 | import android.support.v4.view.ViewPager; 7 | import android.view.KeyEvent; 8 | import android.view.MenuItem; 9 | 10 | import com.bonait.bnframework.R; 11 | import com.bonait.bnframework.manager.ActivityLifecycleManager; 12 | import com.bonait.bnframework.common.base.BaseActivity; 13 | import com.bonait.bnframework.common.utils.ToastUtils; 14 | import com.bonait.bnframework.modules.home.fragment.Home1Fragment; 15 | import com.bonait.bnframework.modules.home.fragment.Home2Fragment; 16 | import com.bonait.bnframework.modules.home.adapter.FragmentAdapter; 17 | import com.bonait.bnframework.modules.mine.fragment.MyFragment; 18 | import com.lzy.okgo.OkGo; 19 | import com.qmuiteam.qmui.widget.QMUIViewPager; 20 | 21 | import butterknife.BindView; 22 | import butterknife.ButterKnife; 23 | 24 | public class BottomNavigation2Activity extends BaseActivity { 25 | 26 | 27 | @BindView(R.id.navigation) 28 | BottomNavigationView bottomNavigationView; 29 | @BindView(R.id.viewpager) 30 | QMUIViewPager viewPager; 31 | 32 | private MenuItem menuItem; 33 | private long exitTime = 0; 34 | 35 | @Override 36 | protected void onCreate(Bundle savedInstanceState) { 37 | super.onCreate(savedInstanceState); 38 | setContentView(R.layout.activity_bottom_navigation2); 39 | ButterKnife.bind(this); 40 | 41 | initFragment(); 42 | viewPager.addOnPageChangeListener(pageChangeListener); 43 | // 设置viewPager缓存多少个fragment 44 | viewPager.setOffscreenPageLimit(3); 45 | bottomNavigationView.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener); 46 | } 47 | 48 | /** 49 | * viewPager里添加fragment 50 | */ 51 | private void initFragment() { 52 | FragmentAdapter fragmentAdapter = new FragmentAdapter(getSupportFragmentManager()); 53 | fragmentAdapter.addFragment(new Home1Fragment()); 54 | fragmentAdapter.addFragment(new Home2Fragment()); 55 | fragmentAdapter.addFragment(new MyFragment()); 56 | viewPager.setAdapter(fragmentAdapter); 57 | } 58 | 59 | //-------------------------配置viewPager与fragment关联----------------------------// 60 | 61 | /** 62 | * 配置bottom底部菜单栏监听器,手指点击底部菜单监听 63 | */ 64 | private BottomNavigationView.OnNavigationItemSelectedListener mOnNavigationItemSelectedListener 65 | = new BottomNavigationView.OnNavigationItemSelectedListener() { 66 | 67 | @Override 68 | public boolean onNavigationItemSelected(@NonNull MenuItem item) { 69 | switch (item.getItemId()) { 70 | case R.id.bottom_navigation_1: 71 | viewPager.setCurrentItem(0); 72 | return true; 73 | case R.id.bottom_navigation_2: 74 | viewPager.setCurrentItem(1); 75 | return true; 76 | case R.id.bottom_navigation_3: 77 | viewPager.setCurrentItem(2); 78 | return true; 79 | } 80 | return false; 81 | } 82 | }; 83 | 84 | 85 | /** 86 | * 配置ViewPager监听器,手指滑动监听 87 | */ 88 | private ViewPager.OnPageChangeListener pageChangeListener = new ViewPager.OnPageChangeListener() { 89 | @Override 90 | public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { 91 | MenuItem menuItem = bottomNavigationView.getMenu().getItem(position); 92 | } 93 | 94 | @Override 95 | public void onPageSelected(int position) { 96 | menuItem = bottomNavigationView.getMenu().getItem(position); 97 | menuItem.setChecked(true); 98 | } 99 | 100 | @Override 101 | public void onPageScrollStateChanged(int state) { 102 | 103 | } 104 | }; 105 | 106 | @Override 107 | protected boolean canDragBack() { 108 | return viewPager.getCurrentItem() == 0; 109 | } 110 | 111 | /** 112 | * 重写返回键,实现双击退出程序效果 113 | */ 114 | @Override 115 | public boolean onKeyDown(int keyCode, KeyEvent event) { 116 | if (keyCode == KeyEvent.KEYCODE_BACK) { 117 | if (System.currentTimeMillis() - exitTime > 2000) { 118 | ToastUtils.normal("再按一次退出程序"); 119 | exitTime = System.currentTimeMillis(); 120 | } else { 121 | OkGo.getInstance().cancelAll(); 122 | overridePendingTransition(android.R.anim.fade_in, android.R.anim.fade_out); 123 | ActivityLifecycleManager.get().appExit(); 124 | } 125 | return true; 126 | } 127 | return super.onKeyDown(keyCode, event); 128 | } 129 | } 130 | -------------------------------------------------------------------------------- /app/src/main/java/com/bonait/bnframework/modules/home/adapter/FragmentAdapter.java: -------------------------------------------------------------------------------- 1 | package com.bonait.bnframework.modules.home.adapter; 2 | 3 | import android.support.annotation.NonNull; 4 | import android.support.v4.app.Fragment; 5 | import android.support.v4.app.FragmentManager; 6 | import android.support.v4.app.FragmentPagerAdapter; 7 | import android.view.ViewGroup; 8 | 9 | import java.util.ArrayList; 10 | import java.util.List; 11 | 12 | /** 13 | * Created by LY on 2019/3/26. 14 | */ 15 | public class FragmentAdapter extends FragmentPagerAdapter { 16 | private List fragments = new ArrayList<>(); 17 | 18 | public FragmentAdapter(FragmentManager fm) { 19 | super(fm); 20 | 21 | } 22 | 23 | @Override 24 | public Fragment getItem(int position) { 25 | return fragments.get(position); 26 | } 27 | 28 | @Override 29 | public int getCount() { 30 | return fragments.size(); 31 | } 32 | 33 | public void addFragment(Fragment fragment) { 34 | fragments.add(fragment); 35 | } 36 | 37 | @NonNull 38 | @Override 39 | public Object instantiateItem(@NonNull ViewGroup container, int position) { 40 | return super.instantiateItem(container, position); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /app/src/main/java/com/bonait/bnframework/modules/home/fragment/Home1Fragment.java: -------------------------------------------------------------------------------- 1 | package com.bonait.bnframework.modules.home.fragment; 2 | 3 | 4 | import android.os.Bundle; 5 | import android.support.annotation.NonNull; 6 | import android.support.annotation.Nullable; 7 | import android.support.v4.app.Fragment; 8 | import android.support.v4.content.ContextCompat; 9 | import android.view.LayoutInflater; 10 | import android.view.View; 11 | 12 | import com.bonait.bnframework.R; 13 | import com.bonait.bnframework.common.base.BaseFragment; 14 | import com.bonait.bnframework.common.utils.ToastUtils; 15 | import com.orhanobut.logger.Logger; 16 | import com.qmuiteam.qmui.widget.QMUITopBar; 17 | 18 | import butterknife.BindView; 19 | import butterknife.ButterKnife; 20 | import butterknife.OnClick; 21 | 22 | /** 23 | * A simple {@link Fragment} subclass. 24 | */ 25 | public class Home1Fragment extends BaseFragment { 26 | 27 | @BindView(R.id.topbar) 28 | QMUITopBar mTopBar; 29 | 30 | public Home1Fragment() { 31 | } 32 | 33 | @Override 34 | protected View onCreateView() { 35 | View root = LayoutInflater.from(getActivity()).inflate(R.layout.fragment_home1, null); 36 | ButterKnife.bind(this, root); 37 | 38 | return root; 39 | } 40 | 41 | @Override 42 | public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { 43 | super.onViewCreated(view, savedInstanceState); 44 | Logger.d("第一页创建"); 45 | initTopBar(); 46 | } 47 | 48 | @OnClick(R.id.button) 49 | public void onViewClicked() { 50 | ToastUtils.info("主页"); 51 | } 52 | 53 | private void initTopBar() { 54 | mTopBar.setBackgroundColor(ContextCompat.getColor(requireContext(), R.color.app_color_theme_4)); 55 | mTopBar.setTitle("沉浸式状态栏示例"); 56 | } 57 | 58 | /*private void initTopBar() { 59 | mTopBar.setBackgroundColor(ContextCompat.getColor(getContext(), R.color.app_color_theme_4)); 60 | 61 | mTopBar.setTitle("沉浸式状态栏示例"); 62 | }*/ 63 | 64 | @Override 65 | public void onDestroy() { 66 | super.onDestroy(); 67 | Logger.d("第一页销毁"); 68 | } 69 | 70 | /** 71 | * 当在activity设置viewPager + BottomNavigation + fragment时, 72 | * 为防止viewPager左滑动切换界面,与fragment左滑返回上一界面冲突引起闪退问题, 73 | * 必须加上此方法,禁止fragment左滑返回上一界面。 74 | * 75 | * 切记!切记!切记!否则会闪退! 76 | * 77 | * 当在fragment设置viewPager + BottomNavigation + fragment时,则不会出现这个问题。 78 | * */ 79 | @Override 80 | protected boolean canDragBack() { 81 | return false; 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /app/src/main/java/com/bonait/bnframework/modules/home/fragment/Home2Fragment.java: -------------------------------------------------------------------------------- 1 | package com.bonait.bnframework.modules.home.fragment; 2 | 3 | 4 | import android.app.Fragment; 5 | import android.os.Bundle; 6 | import android.support.annotation.NonNull; 7 | import android.support.annotation.Nullable; 8 | import android.view.LayoutInflater; 9 | import android.view.View; 10 | 11 | import com.bonait.bnframework.R; 12 | import com.bonait.bnframework.common.base.BaseFragment; 13 | import com.bonait.bnframework.common.utils.ToastUtils; 14 | import com.orhanobut.logger.Logger; 15 | import com.qmuiteam.qmui.widget.QMUITopBarLayout; 16 | 17 | import butterknife.BindView; 18 | import butterknife.ButterKnife; 19 | import butterknife.OnClick; 20 | 21 | /** 22 | * A simple {@link Fragment} subclass. 23 | */ 24 | public class Home2Fragment extends BaseFragment { 25 | 26 | 27 | @BindView(R.id.topbar) 28 | QMUITopBarLayout mTopBar; 29 | 30 | public Home2Fragment() { 31 | } 32 | 33 | @Override 34 | protected View onCreateView() { 35 | View root = LayoutInflater.from(getActivity()).inflate(R.layout.fragment_home2, null); 36 | ButterKnife.bind(this, root); 37 | 38 | 39 | return root; 40 | } 41 | 42 | @Override 43 | public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { 44 | super.onViewCreated(view, savedInstanceState); 45 | Logger.d("第二页创建"); 46 | 47 | initTopBar(); 48 | } 49 | 50 | private void initTopBar() { 51 | mTopBar.setTitle("第二页"); 52 | } 53 | 54 | @OnClick(R.id.button) 55 | public void onViewClicked() { 56 | ToastUtils.info("功能"); 57 | } 58 | 59 | @Override 60 | public void onDestroy() { 61 | super.onDestroy(); 62 | Logger.d("第二页销毁"); 63 | } 64 | 65 | /** 66 | * 当在activity设置viewPager + BottomNavigation + fragment时, 67 | * 为防止viewPager左滑动切换界面,与fragment左滑返回上一界面冲突引起闪退问题, 68 | * 必须加上此方法,禁止fragment左滑返回上一界面。 69 | * 70 | * 切记!切记!切记!否则会闪退! 71 | * 72 | * 当在fragment设置viewPager + BottomNavigation + fragment时,则不会出现这个问题。 73 | * */ 74 | @Override 75 | protected boolean canDragBack() { 76 | return false; 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /app/src/main/java/com/bonait/bnframework/modules/home/fragment/Home3Fragment.java: -------------------------------------------------------------------------------- 1 | package com.bonait.bnframework.modules.home.fragment; 2 | 3 | 4 | import android.app.Fragment; 5 | import android.view.LayoutInflater; 6 | import android.view.View; 7 | 8 | import com.bonait.bnframework.R; 9 | import com.bonait.bnframework.common.base.BaseFragment; 10 | import com.bonait.bnframework.common.utils.ToastUtils; 11 | import com.orhanobut.logger.Logger; 12 | import com.qmuiteam.qmui.widget.QMUITopBarLayout; 13 | 14 | import butterknife.BindView; 15 | import butterknife.ButterKnife; 16 | import butterknife.OnClick; 17 | 18 | /** 19 | * A simple {@link Fragment} subclass. 20 | */ 21 | public class Home3Fragment extends BaseFragment { 22 | 23 | @BindView(R.id.topbar) 24 | QMUITopBarLayout mTopBar; 25 | 26 | public Home3Fragment() { 27 | // Required empty public constructor 28 | } 29 | 30 | @Override 31 | protected View onCreateView() { 32 | View root = LayoutInflater.from(getActivity()).inflate(R.layout.fragment_home3, null); 33 | ButterKnife.bind(this, root); 34 | Logger.d("第三页创建"); 35 | 36 | initTopBar(); 37 | return root; 38 | } 39 | 40 | private void initTopBar() { 41 | mTopBar.setTitle("第三页"); 42 | } 43 | 44 | @OnClick(R.id.button) 45 | public void onViewClicked() { 46 | ToastUtils.info("我的"); 47 | } 48 | 49 | @Override 50 | public void onDestroy() { 51 | super.onDestroy(); 52 | Logger.d("第三页销毁"); 53 | } 54 | 55 | /** 56 | * 当在activity设置viewPager + BottomNavigation + fragment时, 57 | * 为防止viewPager左滑动切换界面,与fragment左滑返回上一界面冲突引起闪退问题, 58 | * 必须加上此方法,禁止fragment左滑返回上一界面。 59 | * 60 | * 切记!切记!切记!否则会闪退! 61 | * 62 | * 若底层是BottomNavigationFragment设置viewPager则不会出现这个问题。 63 | * */ 64 | @Override 65 | protected boolean canDragBack() { 66 | return false; 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /app/src/main/java/com/bonait/bnframework/modules/mine/fragment/MyFragment.java: -------------------------------------------------------------------------------- 1 | package com.bonait.bnframework.modules.mine.fragment; 2 | 3 | import android.Manifest; 4 | import android.content.Context; 5 | import android.content.Intent; 6 | import android.net.Uri; 7 | import android.os.Build; 8 | import android.os.Bundle; 9 | import android.provider.Settings; 10 | import android.support.annotation.NonNull; 11 | import android.support.annotation.Nullable; 12 | import android.support.annotation.RequiresApi; 13 | import android.view.LayoutInflater; 14 | import android.view.View; 15 | import android.widget.ImageView; 16 | import android.widget.TextView; 17 | 18 | import com.allen.library.SuperTextView; 19 | import com.bonait.bnframework.R; 20 | import com.bonait.bnframework.common.base.BaseFragment; 21 | import com.bonait.bnframework.common.constant.Constants; 22 | import com.bonait.bnframework.common.utils.AlertDialogUtils; 23 | import com.bonait.bnframework.common.utils.UpdateAppUtils; 24 | import com.orhanobut.logger.Logger; 25 | import com.qmuiteam.qmui.widget.dialog.QMUIDialog; 26 | import com.qmuiteam.qmui.widget.dialog.QMUIDialogAction; 27 | 28 | import butterknife.BindView; 29 | import butterknife.ButterKnife; 30 | import butterknife.OnClick; 31 | import pub.devrel.easypermissions.AfterPermissionGranted; 32 | import pub.devrel.easypermissions.EasyPermissions; 33 | 34 | public class MyFragment extends BaseFragment { 35 | 36 | 37 | @BindView(R.id.h_background) 38 | ImageView hBackground; 39 | @BindView(R.id.h_head) 40 | ImageView hHead; 41 | @BindView(R.id.h_user_name) 42 | TextView hUserName; 43 | @BindView(R.id.stv_change_pwd) 44 | SuperTextView stvChangePwd; 45 | @BindView(R.id.stv_update) 46 | SuperTextView stvUpdate; 47 | @BindView(R.id.stv_logout) 48 | SuperTextView stvLogout; 49 | 50 | /* 51 | private static final String BUNDLE_TITLE = "key_title"; 52 | public static MyFragment newInstance(String title) { 53 | Bundle bundle = new Bundle(); 54 | bundle.putString(BUNDLE_TITLE,title); 55 | MyFragment myFragment = new MyFragment(); 56 | myFragment.setArguments(bundle); 57 | return myFragment; 58 | } 59 | */ 60 | 61 | private Context context; 62 | 63 | @Override 64 | protected View onCreateView() { 65 | View root = LayoutInflater.from(getActivity()).inflate(R.layout.fragment_my, null); 66 | ButterKnife.bind(this, root); 67 | 68 | return root; 69 | } 70 | 71 | @Override 72 | public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { 73 | super.onViewCreated(view, savedInstanceState); 74 | Logger.d("我的fragment创建"); 75 | context = getContext(); 76 | initView(); 77 | } 78 | 79 | @OnClick(R.id.h_head) 80 | public void onViewClicked() { 81 | 82 | } 83 | 84 | private void initView() { 85 | 86 | /* 87 | * 版本更新,点击事件 88 | * */ 89 | stvUpdate.setOnSuperTextViewClickListener(new SuperTextView.OnSuperTextViewClickListener() { 90 | @Override 91 | public void onClickListener(SuperTextView superTextView) { 92 | //检查权限,并启动版本更新 93 | checkPermission(); 94 | } 95 | }); 96 | } 97 | 98 | 99 | 100 | /***********************************检查App更新********************************************/ 101 | @AfterPermissionGranted(Constants.UPDATE_APP) 102 | @Override 103 | public void checkPermission() { 104 | // 检查文件读写权限 105 | String[] params = {Manifest.permission.WRITE_EXTERNAL_STORAGE}; 106 | if (EasyPermissions.hasPermissions(context,params)) { 107 | 108 | //Android 8.0后,安装应用需要检查打开未知来源应用权限 109 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { 110 | checkInstallPermission(); 111 | } else { 112 | UpdateAppUtils.updateApp(context); 113 | } 114 | } else { 115 | //未获取权限 116 | EasyPermissions.requestPermissions(this, "更新版本需要读写本地权限!", Constants.UPDATE_APP, params); 117 | } 118 | } 119 | 120 | /** 121 | * Android 8.0后,安装应用需要检查打开未知来源应用权限 122 | */ 123 | @RequiresApi(api = Build.VERSION_CODES.O) 124 | private void checkInstallPermission() { 125 | // 判断是否已打开未知来源应用权限 126 | boolean haveInstallPermission = context.getPackageManager().canRequestPackageInstalls(); 127 | 128 | if (haveInstallPermission) { 129 | //已经打开权限,直接启动版本更新 130 | UpdateAppUtils.updateApp(context); 131 | } else { 132 | AlertDialogUtils.showDialog(getContext(), 133 | "请打开未知来源应用权限", 134 | "为了正常升级APP,请点击设置-高级设置-允许安装未知来源应用,本功能只限用于APP版本升级。", 135 | "权限设置", 136 | new QMUIDialogAction.ActionListener() { 137 | @Override 138 | public void onClick(QMUIDialog dialog, int index) { 139 | // 跳转到系统打开未知来源应用权限,在onActivityResult中启动更新 140 | toInstallPermissionSettingIntent(context); 141 | dialog.dismiss(); 142 | } 143 | }); 144 | } 145 | } 146 | 147 | /** 148 | * 开启安装未知来源权限 149 | */ 150 | @RequiresApi(api = Build.VERSION_CODES.O) 151 | private void toInstallPermissionSettingIntent(Context context) { 152 | Uri packageURI = Uri.parse("package:" + context.getPackageName()); 153 | Intent intent = new Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES, packageURI); 154 | startActivityForResult(intent, Constants.INSTALL_PERMISSION_CODE); 155 | } 156 | 157 | @Override 158 | public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { 159 | super.onActivityResult(requestCode, resultCode, data); 160 | 161 | switch (requestCode) { 162 | case Constants.INSTALL_PERMISSION_CODE: 163 | checkPermission(); 164 | break; 165 | } 166 | } 167 | 168 | @Override 169 | public void onDestroy() { 170 | super.onDestroy(); 171 | Logger.d("我的fragment销毁"); 172 | } 173 | 174 | /** 175 | * 当在activity设置viewPager + BottomNavigation + fragment时, 176 | * 为防止viewPager左滑动切换界面,与fragment左滑返回上一界面冲突引起闪退问题, 177 | * 必须加上此方法,禁止fragment左滑返回上一界面。 178 | * 179 | * 切记!切记!切记!否则会闪退! 180 | * 181 | * 当在fragment设置viewPager + BottomNavigation + fragment时,则不会出现这个问题。 182 | */ 183 | @Override 184 | protected boolean canDragBack() { 185 | return false; 186 | } 187 | 188 | } 189 | -------------------------------------------------------------------------------- /app/src/main/java/com/bonait/bnframework/modules/mine/model/UpdateAppPo.java: -------------------------------------------------------------------------------- 1 | package com.bonait.bnframework.modules.mine.model; 2 | 3 | import com.google.gson.annotations.SerializedName; 4 | 5 | import java.util.Date; 6 | 7 | /** 8 | * Created by LY on 2019/4/8. 9 | */ 10 | public class UpdateAppPo { 11 | /** 12 | * apkId : 10140 13 | * createtime : 创建时间 14 | * creator : 发布者 15 | * description : 描述 16 | * fileSize : Apk大小byte 17 | * id : 1 18 | * modifier : null 19 | * updatetime : 更新时间 20 | * version : Apk版本 21 | */ 22 | @SerializedName("apkId") 23 | private String apkId; 24 | @SerializedName("createtime") 25 | private Date createTime; 26 | @SerializedName("creator") 27 | private String creator; 28 | @SerializedName("description") 29 | private String description; 30 | @SerializedName("fileSize") 31 | private String fileSize; 32 | @SerializedName("id") 33 | private int id; 34 | @SerializedName("modifier") 35 | private String modifier; 36 | @SerializedName("updatetime") 37 | private Date updateTime; 38 | @SerializedName("version") 39 | private int version; 40 | 41 | public String getApkId() { 42 | return apkId; 43 | } 44 | 45 | public void setApkId(String apkId) { 46 | this.apkId = apkId; 47 | } 48 | 49 | public Date getCreateTime() { 50 | return createTime; 51 | } 52 | 53 | public void setCreateTime(Date createTime) { 54 | this.createTime = createTime; 55 | } 56 | 57 | public String getCreator() { 58 | return creator; 59 | } 60 | 61 | public void setCreator(String creator) { 62 | this.creator = creator; 63 | } 64 | 65 | public String getDescription() { 66 | return description; 67 | } 68 | 69 | public void setDescription(String description) { 70 | this.description = description; 71 | } 72 | 73 | public String getFileSize() { 74 | return fileSize; 75 | } 76 | 77 | public void setFileSize(String fileSize) { 78 | this.fileSize = fileSize; 79 | } 80 | 81 | public int getId() { 82 | return id; 83 | } 84 | 85 | public void setId(int id) { 86 | this.id = id; 87 | } 88 | 89 | public String getModifier() { 90 | return modifier; 91 | } 92 | 93 | public void setModifier(String modifier) { 94 | this.modifier = modifier; 95 | } 96 | 97 | public Date getUpdateTime() { 98 | return updateTime; 99 | } 100 | 101 | public void setUpdateTime(Date updateTime) { 102 | this.updateTime = updateTime; 103 | } 104 | 105 | public int getVersion() { 106 | return version; 107 | } 108 | 109 | public void setVersion(int version) { 110 | this.version = version; 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /app/src/main/java/com/bonait/bnframework/modules/welcome/activity/WelcomeActivity.java: -------------------------------------------------------------------------------- 1 | package com.bonait.bnframework.modules.welcome.activity; 2 | 3 | import android.content.Intent; 4 | import android.os.Bundle; 5 | import android.os.Handler; 6 | import android.support.v7.app.AppCompatActivity; 7 | import android.view.KeyEvent; 8 | 9 | import com.bonait.bnframework.manager.ActivityLifecycleManager; 10 | import com.bonait.bnframework.common.constant.Constants; 11 | import com.bonait.bnframework.common.constant.SPConstants; 12 | import com.bonait.bnframework.common.http.callback.json.JsonCallback; 13 | import com.bonait.bnframework.common.model.BaseCodeJson; 14 | import com.bonait.bnframework.common.utils.PreferenceUtils; 15 | import com.bonait.bnframework.modules.home.activity.BottomNavigation2Activity; 16 | import com.bonait.bnframework.test.TestActivity; 17 | import com.lzy.okgo.OkGo; 18 | import com.lzy.okgo.model.Response; 19 | 20 | import java.util.concurrent.TimeUnit; 21 | 22 | import okhttp3.OkHttpClient; 23 | 24 | public class WelcomeActivity extends AppCompatActivity { 25 | 26 | private Handler handler = new Handler(); 27 | /* 28 | * 启动模式: 29 | * 1:启动界面时间与App加载时间相等 30 | * 2:设置启动界面2秒后跳转 31 | * */ 32 | private final static int SELECT_MODE = 1; 33 | private OkHttpClient.Builder builder; 34 | 35 | @Override 36 | protected void onCreate(Bundle savedInstanceState) { 37 | super.onCreate(savedInstanceState); 38 | //setContentView(R.layout.activity_welcome); 39 | initWelcome(); 40 | } 41 | 42 | private void initWelcome() { 43 | switch (WelcomeActivity.SELECT_MODE) { 44 | case 1: 45 | fastWelcome(); 46 | break; 47 | case 2: 48 | slowWelcome(); 49 | break; 50 | } 51 | } 52 | 53 | 54 | /*方法1:启动界面时间与App加载时间相等*/ 55 | private void fastWelcome() { 56 | new Thread(new Runnable() { 57 | @Override 58 | public void run() { 59 | //耗时任务,比如加载网络数据 60 | runOnUiThread(new Runnable() { 61 | @Override 62 | public void run() { 63 | //判断token 64 | doPost(); 65 | } 66 | }); 67 | } 68 | }).start(); 69 | } 70 | 71 | /*方法2:设置启动界面2秒后跳转*/ 72 | private void slowWelcome() { 73 | handler.postDelayed(new Runnable() { 74 | @Override 75 | public void run() { 76 | //判断token 77 | doPost(); 78 | } 79 | }, 2000); 80 | } 81 | 82 | 83 | /** 84 | * 请求服务器判断token是否过期 85 | */ 86 | private void doPost() { 87 | //判断是否用户修改过密码 88 | boolean isChangePwd = PreferenceUtils.getBoolean(SPConstants.CHANGE_PWD, false); 89 | if (isChangePwd) { 90 | //若修改过密码,则使token失效 91 | PreferenceUtils.setString(SPConstants.TOKEN, ""); 92 | } 93 | String token = PreferenceUtils.getString(SPConstants.TOKEN, ""); 94 | // 请求后台判断token 95 | String url = Constants.SERVICE_IP + "/checkToken.do"; 96 | 97 | // 修改请求超时时间为6s,与全局超时时间分开 98 | builder = new OkHttpClient.Builder(); 99 | builder.readTimeout(2000, TimeUnit.MILLISECONDS); 100 | builder.writeTimeout(2000, TimeUnit.MILLISECONDS); 101 | builder.connectTimeout(2000, TimeUnit.MILLISECONDS); 102 | 103 | OkGo.>post(url) 104 | .tag(this) 105 | .client(builder.build()) 106 | .params("token", token) 107 | .execute(new JsonCallback>() { 108 | @Override 109 | public void onSuccess(Response> response) { 110 | 111 | // 判断是否开启跳转到测试界面 112 | if (Constants.SKIP_TO_TEST_ACTIVITY) { 113 | skipToTestActivity(); 114 | } else { 115 | skipToMainActivity(); 116 | } 117 | 118 | } 119 | 120 | @Override 121 | public void onError(Response> response) { 122 | super.onError(response); 123 | skipToLoginActivity(); 124 | } 125 | }); 126 | } 127 | 128 | 129 | /** 130 | * 跳转到测试页面 131 | * */ 132 | private void skipToTestActivity() { 133 | // token未过期,跳转到主界面 134 | Intent intent = new Intent(WelcomeActivity.this, TestActivity.class); 135 | intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); 136 | overridePendingTransition(android.R.anim.fade_in, android.R.anim.fade_out); 137 | startActivity(intent); 138 | // 结束所有Activity 139 | ActivityLifecycleManager.get().finishAllActivity(); 140 | } 141 | 142 | 143 | /** 144 | * 跳转到主界面 145 | * */ 146 | private void skipToMainActivity() { 147 | // token未过期,跳转到主界面 148 | Intent intent = new Intent(WelcomeActivity.this, BottomNavigation2Activity.class); 149 | intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); 150 | startActivity(intent); 151 | overridePendingTransition(android.R.anim.fade_in, android.R.anim.fade_out); 152 | // 结束所有Activity 153 | ActivityLifecycleManager.get().finishAllActivity(); 154 | } 155 | 156 | /** 157 | * 跳转到登录页面 158 | * */ 159 | private void skipToLoginActivity() { 160 | // 跳转到登录页面 161 | Intent intent = new Intent(WelcomeActivity.this, LoginActivity.class); 162 | intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); 163 | startActivity(intent); 164 | overridePendingTransition(android.R.anim.fade_in, android.R.anim.fade_out); 165 | // 结束所有Activity 166 | ActivityLifecycleManager.get().finishAllActivity(); 167 | } 168 | 169 | /** 170 | * 屏蔽物理返回键 171 | */ 172 | @Override 173 | public boolean onKeyDown(int keyCode, KeyEvent event) { 174 | if (keyCode == KeyEvent.KEYCODE_BACK) { 175 | return true; 176 | } 177 | return super.onKeyDown(keyCode, event); 178 | } 179 | 180 | @Override 181 | protected void onDestroy() { 182 | OkGo.cancelAll(builder.build()); 183 | 184 | if (handler != null) { 185 | //If token is null, all callbacks and messages will be removed. 186 | handler.removeCallbacksAndMessages(null); 187 | } 188 | super.onDestroy(); 189 | } 190 | 191 | } 192 | -------------------------------------------------------------------------------- /app/src/main/java/com/bonait/bnframework/modules/welcome/model/AppLoginPo.java: -------------------------------------------------------------------------------- 1 | package com.bonait.bnframework.modules.welcome.model; 2 | 3 | import java.util.List; 4 | 5 | /** 6 | * Created by LY on 2019/4/2. 7 | */ 8 | public class AppLoginPo { 9 | 10 | private String token; 11 | private int id; 12 | private String name; 13 | private List roleIds; 14 | private String roleNames; 15 | private String firstDepId; 16 | private String firstDepName; 17 | private String depName; 18 | 19 | public String getToken() { 20 | return token; 21 | } 22 | 23 | public void setToken(String token) { 24 | this.token = token; 25 | } 26 | 27 | public int getId() { 28 | return id; 29 | } 30 | 31 | public void setId(int id) { 32 | this.id = id; 33 | } 34 | 35 | public String getName() { 36 | return name; 37 | } 38 | 39 | public void setName(String name) { 40 | this.name = name; 41 | } 42 | 43 | public List getRoleIds() { 44 | return roleIds; 45 | } 46 | 47 | public void setRoleIds(List roleIds) { 48 | this.roleIds = roleIds; 49 | } 50 | 51 | public String getRoleNames() { 52 | return roleNames; 53 | } 54 | 55 | public void setRoleNames(String roleNames) { 56 | this.roleNames = roleNames; 57 | } 58 | 59 | public String getFirstDepId() { 60 | return firstDepId; 61 | } 62 | 63 | public void setFirstDepId(String firstDepId) { 64 | this.firstDepId = firstDepId; 65 | } 66 | 67 | public String getFirstDepName() { 68 | return firstDepName; 69 | } 70 | 71 | public void setFirstDepName(String firstDepName) { 72 | this.firstDepName = firstDepName; 73 | } 74 | 75 | public String getDepName() { 76 | return depName; 77 | } 78 | 79 | public void setDepName(String depName) { 80 | this.depName = depName; 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /app/src/main/java/com/bonait/bnframework/test/Test.java: -------------------------------------------------------------------------------- 1 | package com.bonait.bnframework.test; 2 | 3 | /** 4 | * Created by LY on 2019/4/3. 5 | */ 6 | public class Test { 7 | } 8 | -------------------------------------------------------------------------------- /app/src/main/res/color/s_app_color_blue_2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/color/s_app_color_gray.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/color/s_btn_blue_bg.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/color/s_btn_blue_border.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/color/s_btn_blue_text.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/color/s_topbar_btn_color.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/icon_pass_gone.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YuiGod/Framework_Android/abc054cace5dcb439e5e5d065e50a2ce04cf6c8f/app/src/main/res/drawable-hdpi/icon_pass_gone.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/icon_pass_visuable.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YuiGod/Framework_Android/abc054cace5dcb439e5e5d065e50a2ce04cf6c8f/app/src/main/res/drawable-hdpi/icon_pass_visuable.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/icon_personal_announcement.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YuiGod/Framework_Android/abc054cace5dcb439e5e5d065e50a2ce04cf6c8f/app/src/main/res/drawable-hdpi/icon_personal_announcement.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/icon_personal_pwd.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YuiGod/Framework_Android/abc054cace5dcb439e5e5d065e50a2ce04cf6c8f/app/src/main/res/drawable-hdpi/icon_personal_pwd.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/icon_personal_sex.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YuiGod/Framework_Android/abc054cace5dcb439e5e5d065e50a2ce04cf6c8f/app/src/main/res/drawable-hdpi/icon_personal_sex.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/icon_personal_sign.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YuiGod/Framework_Android/abc054cace5dcb439e5e5d065e50a2ce04cf6c8f/app/src/main/res/drawable-hdpi/icon_personal_sign.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/icon_personal_update.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YuiGod/Framework_Android/abc054cace5dcb439e5e5d065e50a2ce04cf6c8f/app/src/main/res/drawable-hdpi/icon_personal_update.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/icon_personal_user.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YuiGod/Framework_Android/abc054cace5dcb439e5e5d065e50a2ce04cf6c8f/app/src/main/res/drawable-hdpi/icon_personal_user.png -------------------------------------------------------------------------------- /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-xhdpi/icon_login_pwd.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YuiGod/Framework_Android/abc054cace5dcb439e5e5d065e50a2ce04cf6c8f/app/src/main/res/drawable-xhdpi/icon_login_pwd.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/icon_login_user.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YuiGod/Framework_Android/abc054cace5dcb439e5e5d065e50a2ce04cf6c8f/app/src/main/res/drawable-xhdpi/icon_login_user.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/icon_delete_fill.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YuiGod/Framework_Android/abc054cace5dcb439e5e5d065e50a2ce04cf6c8f/app/src/main/res/drawable-xxhdpi/icon_delete_fill.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/icon_delete_fill_select.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YuiGod/Framework_Android/abc054cace5dcb439e5e5d065e50a2ce04cf6c8f/app/src/main/res/drawable-xxhdpi/icon_delete_fill_select.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/icon_personal_announcement.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YuiGod/Framework_Android/abc054cace5dcb439e5e5d065e50a2ce04cf6c8f/app/src/main/res/drawable-xxhdpi/icon_personal_announcement.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/icon_personal_download_files.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YuiGod/Framework_Android/abc054cace5dcb439e5e5d065e50a2ce04cf6c8f/app/src/main/res/drawable-xxhdpi/icon_personal_download_files.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/icon_personal_pwd.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YuiGod/Framework_Android/abc054cace5dcb439e5e5d065e50a2ce04cf6c8f/app/src/main/res/drawable-xxhdpi/icon_personal_pwd.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/icon_personal_sex.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YuiGod/Framework_Android/abc054cace5dcb439e5e5d065e50a2ce04cf6c8f/app/src/main/res/drawable-xxhdpi/icon_personal_sex.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/icon_personal_sign.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YuiGod/Framework_Android/abc054cace5dcb439e5e5d065e50a2ce04cf6c8f/app/src/main/res/drawable-xxhdpi/icon_personal_sign.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/icon_personal_update.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YuiGod/Framework_Android/abc054cace5dcb439e5e5d065e50a2ce04cf6c8f/app/src/main/res/drawable-xxhdpi/icon_personal_update.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/icon_personal_user.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YuiGod/Framework_Android/abc054cace5dcb439e5e5d065e50a2ce04cf6c8f/app/src/main/res/drawable-xxhdpi/icon_personal_user.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/icon_right.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YuiGod/Framework_Android/abc054cace5dcb439e5e5d065e50a2ce04cf6c8f/app/src/main/res/drawable-xxhdpi/icon_right.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/icon_user_pic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YuiGod/Framework_Android/abc054cace5dcb439e5e5d065e50a2ce04cf6c8f/app/src/main/res/drawable-xxhdpi/icon_user_pic.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/bg_btn_login_selected.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/common_bg_with_radius_and_border.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/delete_selector.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_dashboard_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_home_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /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/drawable/ic_notifications_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/icon_home1_selector.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/icon_home2_selector.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/icon_home_my_selector.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/radius_button_bg.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/radius_button_bg_pressed.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/s_radius_button_bg.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/tab_panel_bg.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 8 | 9 | 10 | 11 | 14 | 15 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/welcome.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_bottom_navigation.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 9 | 16 | 17 | 25 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_bottom_navigation2.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 17 | 18 | 27 | 28 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_test.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 13 | 14 | 21 | 22 | 23 | 24 | 36 | 37 | 38 | 39 | 40 | 41 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 66 | 67 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_welcome.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/layout/fragment_home1.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 10 | 11 | 15 | 16 | 20 | 21 | 22 | 23 | 35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /app/src/main/res/layout/fragment_home2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 14 | 15 | 16 | 17 | 29 | 30 | 31 | 32 | 33 | 38 | 39 | -------------------------------------------------------------------------------- /app/src/main/res/layout/fragment_home3.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 14 | 15 | 16 | 17 | 29 | 30 | 31 | 32 | 33 | 38 | 39 | -------------------------------------------------------------------------------- /app/src/main/res/layout/fragment_my.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 14 | 15 | 18 | 19 | 25 | 26 | 32 | 33 | 43 | 44 | 45 | 46 | 49 | 50 | 56 | 57 | 67 | 68 | 77 | 78 | 87 | 88 | 96 | 97 | 104 | 105 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | -------------------------------------------------------------------------------- /app/src/main/res/layout/toast_layout.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 14 | 15 | 19 | 20 | -------------------------------------------------------------------------------- /app/src/main/res/menu/navigation.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 8 | 9 | 13 | 14 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /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_check_white_48dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YuiGod/Framework_Android/abc054cace5dcb439e5e5d065e50a2ce04cf6c8f/app/src/main/res/mipmap-hdpi/ic_check_white_48dp.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_clear_white_48dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YuiGod/Framework_Android/abc054cace5dcb439e5e5d065e50a2ce04cf6c8f/app/src/main/res/mipmap-hdpi/ic_clear_white_48dp.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_error_outline_white_48dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YuiGod/Framework_Android/abc054cace5dcb439e5e5d065e50a2ce04cf6c8f/app/src/main/res/mipmap-hdpi/ic_error_outline_white_48dp.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_info_outline_white_48dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YuiGod/Framework_Android/abc054cace5dcb439e5e5d065e50a2ce04cf6c8f/app/src/main/res/mipmap-hdpi/ic_info_outline_white_48dp.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YuiGod/Framework_Android/abc054cace5dcb439e5e5d065e50a2ce04cf6c8f/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YuiGod/Framework_Android/abc054cace5dcb439e5e5d065e50a2ce04cf6c8f/app/src/main/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/toast_frame.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YuiGod/Framework_Android/abc054cace5dcb439e5e5d065e50a2ce04cf6c8f/app/src/main/res/mipmap-hdpi/toast_frame.9.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YuiGod/Framework_Android/abc054cace5dcb439e5e5d065e50a2ce04cf6c8f/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YuiGod/Framework_Android/abc054cace5dcb439e5e5d065e50a2ce04cf6c8f/app/src/main/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YuiGod/Framework_Android/abc054cace5dcb439e5e5d065e50a2ce04cf6c8f/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YuiGod/Framework_Android/abc054cace5dcb439e5e5d065e50a2ce04cf6c8f/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YuiGod/Framework_Android/abc054cace5dcb439e5e5d065e50a2ce04cf6c8f/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YuiGod/Framework_Android/abc054cace5dcb439e5e5d065e50a2ce04cf6c8f/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/icon_tabbar_component.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YuiGod/Framework_Android/abc054cace5dcb439e5e5d065e50a2ce04cf6c8f/app/src/main/res/mipmap-xxhdpi/icon_tabbar_component.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/icon_tabbar_component_selected.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YuiGod/Framework_Android/abc054cace5dcb439e5e5d065e50a2ce04cf6c8f/app/src/main/res/mipmap-xxhdpi/icon_tabbar_component_selected.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/icon_tabbar_lab.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YuiGod/Framework_Android/abc054cace5dcb439e5e5d065e50a2ce04cf6c8f/app/src/main/res/mipmap-xxhdpi/icon_tabbar_lab.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/icon_tabbar_lab_selected.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YuiGod/Framework_Android/abc054cace5dcb439e5e5d065e50a2ce04cf6c8f/app/src/main/res/mipmap-xxhdpi/icon_tabbar_lab_selected.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/icon_tabbar_util.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YuiGod/Framework_Android/abc054cace5dcb439e5e5d065e50a2ce04cf6c8f/app/src/main/res/mipmap-xxhdpi/icon_tabbar_util.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/icon_tabbar_util_selected.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YuiGod/Framework_Android/abc054cace5dcb439e5e5d065e50a2ce04cf6c8f/app/src/main/res/mipmap-xxhdpi/icon_tabbar_util_selected.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YuiGod/Framework_Android/abc054cace5dcb439e5e5d065e50a2ce04cf6c8f/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YuiGod/Framework_Android/abc054cace5dcb439e5e5d065e50a2ce04cf6c8f/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/values/attr.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 | #00A8E1 9 | #8000A8E1 10 | #c000A8E1 11 | 12 | #31BDF3 13 | #7F31BDF3 14 | #7F31BDF3 15 | 16 | #EF5362 17 | #FE6D4B 18 | #FFCF47 19 | #9FD661 20 | #3FD0AD 21 | #2BBDF3 22 | #5A9AEF 23 | #AC8FEF 24 | #EE85C1 25 | 26 | @color/qmui_config_color_gray_5 27 | 28 | #D4D6D8 29 | #ffffff 30 | @color/bar_divider 31 | 32 | 33 | @color/app_color_theme_2 34 | @color/app_color_theme_1 35 | #7FEF5362 36 | 37 | 38 | 39 | 40 | @color/app_color_theme_4 41 | @color/app_color_blue 42 | @color/app_color_theme_3 43 | 44 | #FFFFFF 45 | #000000 46 | #333333 47 | #999999 48 | #CCCCCC 49 | #E0E0E0 50 | #666666 51 | #66000000 52 | #EEEEEE 53 | #00000000 54 | #EEEEEE 55 | #004684 56 | #80000000 57 | 58 | 59 | 60 | #FFFFFF 61 | #11112233 62 | #0288D1 63 | #333333 64 | 65 | #F0F0F0 66 | #FFFFFF 67 | #B0B0B0 68 | #666666 69 | #57C5E8 70 | 71 | #F44336 72 | #D32F2F 73 | #E91E63 74 | #C2185B 75 | #9C27B0 76 | #7B1FA2 77 | #673AB7 78 | #512DA8 79 | #3F51B5 80 | #303F9F 81 | #2196F3 82 | #1976D2 83 | #03A9F4 84 | #0288D1 85 | #00bcd4 86 | #0097A7 87 | #009688 88 | #00796B 89 | #4CAF50 90 | #388E3C 91 | #8BC34A 92 | #689F38 93 | #CDDC39 94 | #AFB42B 95 | #FFEB3B 96 | #FBC02D 97 | #CDCDB4 98 | #FFC107 99 | #FFA000 100 | #ff9800 101 | #F57C00 102 | #FF5722 103 | #E64A19 104 | #795548 105 | #5D4037 106 | #9E9E9E 107 | #616161 108 | #607d8b 109 | #455A64 110 | 111 | -------------------------------------------------------------------------------- /app/src/main/res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 49dp 5 | @dimen/qmui_content_spacing_horizontal 6 | 7 | 8 | 1px 9 | -1px 10 | 11 | 12 | 13 | 46dp 14 | 23dp 15 | 10dp 16 | 35dp 17 | 18 | 19 | 30dp 20 | 21 | 22 | 35dp 23 | 20dp 24 | 50dp 25 | 26 | 27 | 35dp 28 | 16sp 29 | 30 | 16dp 31 | 16dp 32 | 33 | 34 | 50dp 35 | 75dp 36 | 35dp 37 | 50dp 38 | 10dp 39 | 4dp 40 | 40dp 41 | 14sp 42 | 43 | -------------------------------------------------------------------------------- /app/src/main/res/values/ids.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | Framework 3 | 4 | 5 | Hello blank fragment 6 | 标题 7 | 主页 8 | 功能 9 | 请输入用户名 10 | 我的 11 | 12 | -------------------------------------------------------------------------------- /app/src/main/res/xml/app_provider_paths.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 8 | 9 | 12 | 13 | 16 | 17 | 20 | 21 | 24 | 25 | 28 | 31 | -------------------------------------------------------------------------------- /app/src/main/res/xml/network_security_config.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /app/src/test/java/com/bonait/bnframework/ExampleUnitTest.java: -------------------------------------------------------------------------------- 1 | package com.bonait.bnframework; 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 | } -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | 3 | buildscript { 4 | repositories { 5 | google() 6 | jcenter() 7 | 8 | } 9 | dependencies { 10 | classpath 'com.android.tools.build:gradle:3.4.1' 11 | 12 | // NOTE: Do not place your application dependencies here; they belong 13 | // in the individual module build.gradle files 14 | } 15 | } 16 | 17 | allprojects { 18 | repositories { 19 | google() 20 | jcenter() 21 | 22 | maven { url "https://jitpack.io" } 23 | 24 | } 25 | } 26 | 27 | task clean(type: Delete) { 28 | delete rootProject.buildDir 29 | } 30 | 31 | ext { // 统一版本入口 32 | //App版本号 33 | versionCode = 1 34 | versionName = "1.0.0" 35 | 36 | // 支持Android版本 37 | buildToolsVersion = "28.0.3" 38 | minSdkVersion = 23 39 | targetSdkVersion = 28 40 | compileSdkVersion = 28 41 | 42 | // 支持包 43 | supportVersion = "28.0.0" 44 | butterknife = "8.8.1" 45 | } 46 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | # IDE (e.g. Android Studio) users: 3 | # Gradle settings configured through the IDE *will override* 4 | # any settings specified in this file. 5 | # For more details on how to configure your build environment visit 6 | # http://www.gradle.org/docs/current/userguide/build_environment.html 7 | # Specifies the JVM arguments used for the daemon process. 8 | # The setting is particularly useful for tweaking memory settings. 9 | org.gradle.jvmargs=-Xmx1536m 10 | # When configured, Gradle will run in incubating parallel mode. 11 | # This option should only be used with decoupled projects. More details, visit 12 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 13 | # org.gradle.parallel=true 14 | 15 | 16 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YuiGod/Framework_Android/abc054cace5dcb439e5e5d065e50a2ce04cf6c8f/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Thu Apr 18 09:23:33 CST 2019 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-5.1.1-all.zip 7 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /img_folder/im_login.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YuiGod/Framework_Android/abc054cace5dcb439e5e5d065e50a2ce04cf6c8f/img_folder/im_login.png -------------------------------------------------------------------------------- /img_folder/im_pager1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YuiGod/Framework_Android/abc054cace5dcb439e5e5d065e50a2ce04cf6c8f/img_folder/im_pager1.png -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 2 | --------------------------------------------------------------------------------