Compare commits

...

92 Commits

Author SHA1 Message Date
fengjignqi
0c692c77bd 优化 2026-08-19 16:07:09 +08:00
fengjignqi
22f197a929 优化 2026-07-30 14:03:11 +08:00
fengjignqi
b25e3540fb 优化 2026-07-27 14:06:12 +08:00
fengjignqi
ec59249b3b 优化 2026-07-20 15:47:08 +08:00
fengjignqi
192ca7d3a4 优化 2026-07-17 15:34:23 +08:00
fengjignqi
69830dfc69 优化密码相关,隐藏/显示 2026-07-15 11:35:32 +08:00
fengjignqi
a9ed6f9452 优化 2026-07-15 10:02:14 +08:00
fengjignqi
5dae94788c 优化 2026-07-14 18:00:38 +08:00
fengjignqi
a31443fa4c 优化 2026-07-13 14:54:21 +08:00
fengjignqi
3f0260a37a 优化 2026-07-10 15:22:01 +08:00
fengjignqi
ed9c825bc7 优化 2026-07-09 11:30:50 +08:00
fengjignqi
79e51ad044 注销账号 2026-07-08 14:15:21 +08:00
fengjignqi
1cfc6f9d73 排程进度 2026-07-06 16:48:39 +08:00
fengjignqi
fa44e0edbd 优化 2026-07-06 10:35:56 +08:00
fengjignqi
d8d546c90a 优化 2026-07-04 10:47:05 +08:00
fengjignqi
01e4f0aefa 优化配网进度实时更新 2026-07-03 15:48:47 +08:00
fengjignqi
5a72fd98af 更新版本 2026-07-03 11:42:04 +08:00
fengjignqi
21d834d805 更新版本 2026-07-03 11:08:07 +08:00
fengjignqi
d2610d5b61 检测版本更新App 2026-07-02 08:45:59 +08:00
fengjignqi
b5e9f0de3b 图片上传 2026-06-29 17:59:39 +08:00
fengjignqi
f53408654b 图片上传 2026-06-29 16:57:43 +08:00
fengjignqi
fbef699b50 优化浇水流程,以及中英文遗漏点 2026-06-29 14:13:31 +08:00
fengjignqi
73d5003655 优化浇水流程,以及中英文遗漏点 2026-06-26 10:12:45 +08:00
fengjignqi
5e920037f5 去除部分无用类 2026-06-24 10:34:28 +08:00
fengjignqi
a4f9d630df 去除部分无用类 2026-06-24 10:05:39 +08:00
fengjignqi
133045fadd 优化401,以及部分中英文显示调整 2026-06-22 18:00:08 +08:00
fengjignqi
5842837a9e 修复401报错 2026-06-22 14:40:54 +08:00
fengjignqi
bc3091ac02 优化开启浇水 2026-06-17 11:34:23 +08:00
fengjignqi
d4cc897e26 优化开启浇水 2026-06-17 10:01:33 +08:00
fengjignqi
8b3c6d1761 修改蓝牙连接、配网时动画设置。 2026-06-17 08:42:54 +08:00
fengjignqi
92ca8067d2 调整App内获取授权的位置 2026-06-16 14:49:32 +08:00
fengjignqi
45dfc2d793 更换wifi扫描模式,从设备获取回传Wifi列表。 2026-06-14 15:23:33 +08:00
fengjignqi
dab61da6c5 扫描二维码,连接配网1 2026-06-14 09:06:26 +08:00
fengjignqi
4d4df82c6e 扫描二维码,连接配网1 2026-06-12 17:30:12 +08:00
fengjignqi
56af585524 扫描蓝牙二维码,准备配网 2026-06-12 08:37:00 +08:00
fengjignqi
02acc5403d 蓝牙连接不稳定修复 2026-06-11 09:23:33 +08:00
fengjignqi
2a933d09a4 蓝牙连接不稳定修复 2026-06-10 11:34:47 +08:00
fengjignqi
121c69fdfc 修改有关于设备相关的接口,入参参数更改 2026-06-10 08:20:26 +08:00
fengjignqi
97ee780561 语言中英文完善 2026-06-09 11:24:15 +08:00
fengjignqi
77f6001a31 语言中英文完善 2026-06-09 10:50:23 +08:00
fengjignqi
e040be11c3 语言中英文完善 2026-06-06 18:01:18 +08:00
fengjignqi
bafd193a96 语言选择 2026-06-06 16:16:52 +08:00
fengjignqi
b621a77e8d 语言选择 2026-06-06 15:25:52 +08:00
fengjignqi
e9c17d355a 适配黑色主题,调整细节14:26 2026-06-06 14:26:38 +08:00
fengjignqi
e0249fa0fa 适配黑色主题,调整细节 2026-06-06 10:47:02 +08:00
fengjignqi
bc270205d0 权限调整 2026-06-05 09:17:02 +08:00
fengjignqi
e40cf952c0 连接蓝牙,配网 2026-06-04 17:48:36 +08:00
fengjignqi
edfa6331f5 连接蓝牙,配网 2026-06-04 16:49:14 +08:00
fengjignqi
7e63101fc9 连接蓝牙,配网 2026-06-04 14:30:24 +08:00
fengjignqi
0f9c8c7329 显示附近蓝牙设备 2026-06-04 08:49:28 +08:00
fengjignqi
20a08e9b61 显示附近蓝牙设备 2026-06-03 16:47:42 +08:00
fengjignqi
07edcb4664 引入蓝牙依赖 2026-06-03 16:25:13 +08:00
fengjignqi
5089e760e5 历史记录筛选 2026-06-03 15:43:43 +08:00
fengjignqi
2507657285 历史记录筛选 2026-06-03 15:14:49 +08:00
fengjignqi
bd75b8baeb 历史记录筛选 2026-06-02 18:00:45 +08:00
fengjignqi
03e67932b1 电池电量icon优化 2026-06-02 13:58:54 +08:00
fengjignqi
b7ab2e69a4 排程浇水历史记录 2026-06-01 15:54:06 +08:00
fengjignqi
694b74cda7 排程部分功能优化,
解绑,删除,绑定
2026-05-30 16:32:17 +08:00
fengjignqi
7aed064ddb 排程部分功能优化,
解绑,删除,绑定
2026-05-30 15:53:15 +08:00
fengjignqi
89df3119f8 排程部分功能优化,
解绑,删除,绑定
2026-05-30 09:01:24 +08:00
fengjignqi
ed9cdaf126 排程解绑设备,添加已关联设备tab 2026-05-29 18:02:04 +08:00
fengjignqi
436b65c5e6 更新后新增排程提交 2026-05-29 16:28:55 +08:00
fengjignqi
5a42515f77 更新后新增排程提交 2026-05-29 15:10:40 +08:00
fengjignqi
a8b9aabf20 更新后新增排程提交 2026-05-29 10:47:02 +08:00
fengjignqi
e1d13665ab 更新后新增排程提交 2026-05-29 10:24:43 +08:00
fengjignqi
1000c43321 更新后新增排程提交 2026-05-29 10:18:41 +08:00
fengjignqi
9318646aa4 time配置校验时间冲突 2026-05-29 08:17:06 +08:00
fengjignqi
644a68d865 time列表设置时间 2026-05-28 17:58:32 +08:00
fengjignqi
693acda192 time列表设置时间 2026-05-28 17:11:04 +08:00
fengjignqi
967ddca167 侧滑删除 2026-05-28 16:54:28 +08:00
fengjignqi
9d41f8c1eb 侧滑删除 2026-05-28 15:45:42 +08:00
fengjignqi
21f70b68eb 排程重做 2026-05-28 15:18:57 +08:00
fengjignqi
79e66a20ef 排程重做 2026-05-28 14:56:39 +08:00
fengjignqi
401d1892bb 排程重做 2026-05-28 12:00:18 +08:00
fengjignqi
47769d1003 编辑排程状态 2026-05-27 17:08:57 +08:00
fengjignqi
f7bee61a56 编辑排程状态 2026-05-27 15:47:23 +08:00
fengjignqi
20aaf98235 排程分页2 2026-05-27 10:01:09 +08:00
fengjignqi
30e88c8067 排程分页 2026-05-27 09:41:27 +08:00
fengjignqi
0ca0a395cd 排程编辑更新 2026-05-27 08:52:18 +08:00
fengjignqi
f2b8062398 排程编辑更新 2026-05-26 17:41:27 +08:00
fengjignqi
9ab6d134ab 排程编辑更新 2026-05-26 17:35:08 +08:00
fengjignqi
65dfc1b5f1 排程编辑更新 2026-05-26 15:31:26 +08:00
fengjignqi
5ca81f565a 排程详情 2026-05-26 14:25:41 +08:00
fengjignqi
1ed3a68a5e 手机号、邮箱 + 验证码修改密码 2026-05-26 10:47:46 +08:00
fengjignqi
e14bdaf046 新增排程接口+排程更新 2026-05-26 09:06:11 +08:00
fengjignqi
6c6d211701 新增排程接口 2026-05-25 15:43:34 +08:00
fengjignqi
e6e3f755d0 新增排程接口 2026-05-25 10:16:33 +08:00
fengjignqi
819965faec 新增排程接口 2026-05-25 09:52:26 +08:00
fengjignqi
f86fedd6f1 新增排程页面重做 2026-05-22 15:05:27 +08:00
fengjignqi
1b7c8f0c2d 修改密码 2026-05-21 18:00:42 +08:00
fengjignqi
c90d26afc1 修改设备信息/解绑设备 2026-05-20 16:54:41 +08:00
fengjignqi
dcce26edf2 修改设备信息 2026-05-20 14:50:35 +08:00
264 changed files with 12300 additions and 6596 deletions

View File

@@ -4,10 +4,10 @@
<selectionStates>
<SelectionState runConfigName="app">
<option name="selectionMode" value="DROPDOWN" />
<DropdownSelection timestamp="2026-05-19T02:00:28.842946500Z">
<DropdownSelection timestamp="2026-07-14T09:31:19.203364400Z">
<Target type="DEFAULT_BOOT">
<handle>
<DeviceId pluginId="PhysicalDevice" identifier="serial=D122222104A9" />
<DeviceId pluginId="Default" identifier="serial=emulator-5554;connection=53435af5" />
</handle>
</Target>
</DropdownSelection>

View File

@@ -3,6 +3,10 @@
<component name="DeviceTable">
<option name="columnSorters">
<list>
<ColumnSorterState>
<option name="column" value="Name" />
<option name="order" value="ASCENDING" />
</ColumnSorterState>
<ColumnSorterState>
<option name="column" value="API" />
<option name="order" value="DESCENDING" />

View File

@@ -4,7 +4,7 @@ apply plugin: 'com.hihonor.mcs.asplugin'
apply plugin: 'io.freefair.lombok' // ✅ 加上这个
android {
compileSdkVersion 33
compileSdkVersion 34
lintOptions {
checkReleaseBuilds false // 关闭 release 打包时 lint 检查
abortOnError false // 即使有错误也不终止编译
@@ -39,7 +39,7 @@ android {
minSdkVersion 26
targetSdkVersion 30
versionCode 1
versionName "1.0.1"//version 1.0.0-appstore version 1.0.0-xh
versionName "Version 1.0.1"//version 1.0.0-appstore version 1.0.0-xh
// 添加自定义字段
buildConfigField "String", "APP_VERSION_NAME", "\"${versionName}\""
buildConfigField "int", "APP_VERSION_CODE", "${versionCode}"
@@ -121,6 +121,7 @@ dependencies {
implementation project(path: ':imagepickerl')
//消息传递
implementation 'de.greenrobot:eventbus:3.0.0-beta1'
implementation 'org.greenrobot:eventbus:3.3.1'
implementation 'com.trello.rxlifecycle2:rxlifecycle:2.2.1'
implementation 'com.trello.rxlifecycle2:rxlifecycle-android:2.2.1'
implementation 'com.trello.rxlifecycle2:rxlifecycle-components:2.2.1'
@@ -159,8 +160,8 @@ dependencies {
//鲁班图片压缩
implementation 'top.zibin:Luban:1.1.8'
//带有侧滑功能的recyclerview
// implementation 'com.yanzhenjie.recyclerview:x:1.3.2'
implementation 'com.github.luqiming666:SwipeRecyclerView:1.4.8'
implementation 'com.yanzhenjie.recyclerview:x:1.3.2'
// implementation 'com.github.luqiming666:SwipeRecyclerView:1.4.8'
//Activity与Fragmen实现沉浸式状态栏
implementation 'com.github.tangguna:immersion:1.0.1'
//viewpager2
@@ -173,7 +174,7 @@ dependencies {
implementation 'com.github.ns3chz:Picker:1.0.2'
implementation 'com.github.zzy0516alex:FileSelectorRelease:v6.2'
implementation 'com.github.chrisbanes:PhotoView:2.3.0'
implementation 'androidx.appcompat:appcompat:1.3.1'//(最低版本)
implementation 'androidx.appcompat:appcompat:1.6.1'//(最低版本)
// implementation 'com.umeng.umsdk:share-wx:7.1.5' //微信完整版
// implementation 'com.tencent.mm.opensdk:wechat-sdk-android-without-mta:6.7.0'//微信官方依赖库,必选
//商品评价星星
@@ -226,6 +227,13 @@ dependencies {
implementation "androidx.camera:camera-camera2:1.0.2"
implementation "androidx.camera:camera-lifecycle:1.0.2"
implementation "androidx.camera:camera-view:1.0.0-alpha25"
//蓝牙扫描
implementation 'no.nordicsemi.android.support.v18:scanner:1.6.0'
//蓝牙通讯
implementation 'no.nordicsemi.android:ble:2.11.0'
//espressif官方sdk用于esp固件的扫描配网等。
implementation 'com.github.espressif:esp-idf-provisioning-android:lib-2.2.3'
//自定义progressBar
implementation 'com.timqi.sectorprogressview:library:2.0.1'
}

Binary file not shown.

View File

@@ -35,6 +35,15 @@
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<!-- 蓝牙权限 -->
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<!-- 支持ble的设备 -->
<uses-feature
android:name="android.hardware.bluetooth_le"
android:required="true" />
<!--后台获取位置信息,若需后台定位则必选-->
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
<!--用于申请调用A-GPS模块,卫星定位加速-->
@@ -56,14 +65,16 @@
<application
android:name="com.ckkj.water.MyApplication"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:icon="@mipmap/app_logo"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher"
android:roundIcon="@mipmap/app_logo"
android:requestLegacyExternalStorage="true"
android:theme="@style/custom_app_theme"
android:supportsRtl="true"
android:hardwareAccelerated="true"
android:networkSecurityConfig="@xml/network_security_config">
android:networkSecurityConfig="@xml/network_security_config"
android:localeConfig="@xml/locale_config"
tools:replace="android:localeConfig">
<!-- 高德地图 -->
<meta-data android:name="com.amap.api.v2.apikey" android:value="a91364c6bbc2f5c773a949926fae7fb6">
</meta-data>
@@ -111,15 +122,11 @@
android:launchMode="singleTask"
android:screenOrientation="portrait"
android:windowSoftInputMode="adjustResize"/>
<activity
android:name="com.ckkj.water.chat.ChatHistoryActivity"
android:screenOrientation="portrait"
android:windowSoftInputMode="adjustResize"/>
<activity
android:name="com.ckkj.water.login.LoginActivity"
android:theme="@style/AppTheme.FullScreen"
android:screenOrientation="portrait"
android:windowSoftInputMode="adjustResize"/>
android:windowSoftInputMode="adjustPan"/>
<activity
android:name="com.ckkj.water.mine.WebviewUserAgreement"
android:screenOrientation="portrait"
@@ -230,4 +237,4 @@
android:windowSoftInputMode="adjustResize"/>
</application>
</manifest>
</manifest>

View File

@@ -1,7 +1,10 @@
package com.ckkj.water;
public class AppConfig {
//用户当前保存的语言状态,用于接口请求头传参
//zh_CN 中文
//en_US 英文
public static String LOCAL_LANUAGE = "zh_CN";
/**************************生产*******************************/
@@ -12,13 +15,14 @@ public class AppConfig {
/**************************测试*******************************/
// public static String BASE_URL = "http://47.106.83.229:8081/";//测试http://47.106.83.166:8001/
// public static String BASE_URL = "http://47.106.83.229:8081/";//测试http://47.106.83.166:8001/ .
// public static String BASE_URL_TWO = BASE_URL;//测试
// public static String BASE_URL_THREE = BASE_URL;//测试
// public static boolean IS_TEST_REQUEST = true;
/**************************本地*******************************/
public static String BASE_URL = "http://192.168.1.217:8081/";//测试
public static String BASE_URL = "http://192.168.1.217:8082/";//后端本地测试
// public static String BASE_URL = "http://47.97.217.123:8081/";//服务器测试
public static String BASE_URL_TWO = BASE_URL;//测试
public static String BASE_URL_THREE = BASE_URL;//测试
public static boolean IS_TEST_REQUEST = true;
@@ -110,9 +114,9 @@ public class AppConfig {
//测试使用 token
public static String TEST_USER_ID = "1897194667309666304";
//用户协议
public static String USER_AGREEMENT = "https://sta.mingdengbazi.site/yhxy.html";
public static String USER_AGREEMENT = "http://47.97.217.123/user-agreement";
//隐私政策
public static String USER_PRIVACY = "https://sta.mingdengbazi.site/ysxy.html";
public static String USER_PRIVACY = "http://47.97.217.123/privacy";
//用户分享链接
public static String USER_SHARE_URL = "https://sta.mingdengbazi.site/on/index.html?code=";
@@ -120,4 +124,7 @@ public class AppConfig {
public static String APP_CLIENT_ID = "428a8310cd442757ae699df5d894f051";
public static String APP_USER_TYPE = "app_user";
//蓝牙设备的uuid
public static String BLUETOOTH_DEVICE_UUID = "1775244d-6b43-439b-877c-060f2d9bed07";
}

View File

@@ -41,13 +41,17 @@ public class ConstantUtil {
public static final int ACCESS_FINE_LOCATION = 1;
//授权读取文件
public static final int WRITE_FILE_PERMISSON_CPDE = 1001;
public static final int POST_NOTIFICATIONS_PERMISSION_CODE = 1002;
//读取文件
public static final int READ_EXTERNAL_STORAGE = 2;
//相机权限
public static final int CAMERA_AUTH_CODE = 1003;
//快速下单,下载模板到手机
public static final int DOWN_TEMPLATE_CODE = 1004;
/***************设备相关*******************/
//设备解绑成功广播
public static final String DEVICE_UNBIND_SUCCESS = "device_unbind_success";
//应用语言设置
public static final String KEY_APP_LANGUAGE = "key_app_language";
}

View File

@@ -10,6 +10,7 @@ public class EventMessage {
public static final String DATA_REFRESH_EVENT = "data_refresh_event";
public static final String USER_LOGIN_LOST = "user_login_lost";
public static final String CODE_LOGIN_LOST = "code_login_lost";
public static final String ACTIVITY_FINISH = "activity_finish";
public static final String WX_PAY_SUCCESS = "wx_pay_success";
public static final String USER_LOGIN_SUCCESS = "user_login_success";
public static final String HISTORY_SESSIONID_DELETE_SUCCESS = "history_sessionid_delete_success";

View File

@@ -11,11 +11,12 @@ import android.util.Log;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.ckkj.water.base.entity.MineUserInfoBean;
import com.ckkj.water.mine.entity.MineUserInfoBean;
import com.google.gson.Gson;
import com.ckkj.water.login.entity.LoginEntity;
import com.ckkj.water.network.NetWorkManager;
import com.ckkj.water.utils.dataUtil.SharePreUtil;
import com.ckkj.water.utils.manager.LanguageManager;
import com.ckkj.water.utils.manager.ThemeManager;
import com.ckkj.water.utils.manager.WaterUserInfoManager;
import java.util.List;
@@ -67,6 +68,12 @@ public class MyApplication extends Application {
instance = this;
context = getApplicationContext();
// 恢复应用语言设置
applyStoredLocale();
// 检查并设置默认主题色(如果之前没有设置过,默认设为白色主题)
applyDefaultTheme();
boolean isUserAgreed = SharePreUtil.getBoolean(ConstantUtil.SHARE_PRE_NAME,context,ConstantUtil.PRIVACY_POLICY_AGREED);
if(isUserAgreed){
initializeUmengSDK();
@@ -149,11 +156,12 @@ public class MyApplication extends Application {
public void onActivityDestroyed(Activity activity) {}
});
AutoSizeConfig.getInstance()
// 是否使用设备真实尺寸
.setUseDeviceSize(true)
// 是否支持 fragment
.setCustomFragment(true);
// AutoSizeConfig.getInstance()
// // 是否使用设备真实尺寸
// .setUseDeviceSize(true)
// // 是否支持 fragment
// .setCustomFragment(true);
android.util.Log.e("TEST", "hello");
}
private boolean shouldInit() {
@@ -177,4 +185,26 @@ public class MyApplication extends Application {
public static Context getContext() {
return context;
}
/**
* 应用启动时恢复保存的语言设置
* 使用 AppCompatDelegate.setApplicationLocales() API
*/
private void applyStoredLocale() {
LanguageManager.applyStoredLocale();
}
/**
* 检查并设置默认主题色
* 如果之前没有设置过主题(默认为 MODE_FOLLOW_SYSTEM则设置为白色主题MODE_LIGHT
*/
private void applyDefaultTheme() {
int currentTheme = ThemeManager.getCurrentTheme(context);
if (currentTheme == ThemeManager.MODE_FOLLOW_SYSTEM) {
ThemeManager.setCurrentTheme(context, ThemeManager.MODE_LIGHT);
ThemeManager.applyTheme(ThemeManager.MODE_LIGHT);
} else {
ThemeManager.applyTheme(currentTheme);
}
}
}

View File

@@ -20,6 +20,7 @@ import android.os.Bundle;
import android.os.Handler;
import android.provider.MediaStore;
import android.text.InputFilter;
import android.text.InputType;
import android.text.Spanned;
import android.text.TextUtils;
import android.util.Log;
@@ -42,6 +43,7 @@ import androidx.appcompat.app.AppCompatDelegate;
import androidx.core.app.ActivityCompat;
import androidx.viewbinding.ViewBinding;
import com.ckkj.water.dialog.LoadingProgressDialog;
import com.ckkj.water.utils.manager.ThemeManager;
import com.esafirm.imagepicker.features.ImagePicker;
import com.hjq.permissions.OnPermissionCallback;
@@ -100,6 +102,11 @@ public abstract class BaseActivity<T extends ViewBinding, P extends IPresenter>
public static final int REQUEST_EVENT_CODE_10001 = 10001;
public static final int REQUEST_EVENT_CODE_10002 = 10002;
public static final int REQUEST_EVENT_CODE_10003 = 10003;
public static final int INPUT_TYPE_NORMAL = 0; // 默认
public static final int INPUT_TYPE_NUMBER = 1; // 数字
public static final int INPUT_TYPE_LETTER = 2; // 英文字母
public static final int INPUT_TYPE_CHINESE = 3; // 中文
public static final int INPUT_TYPE_NUMBER_LETTER = 4;//数字+字母
public InputFilter mInputFilter;
private static final AtomicBoolean isDialogShown = new AtomicBoolean(false); // 使用 AtomicBoolean 保证线程安全
private ObjectAnimator rotateAnimator;
@@ -187,6 +194,7 @@ public abstract class BaseActivity<T extends ViewBinding, P extends IPresenter>
if (message.msg.equals(EventMessage.USER_LOGIN_LOST)) {
Log.d("DINGDING","Activity接收一次");
Log.d("DINGDING", "触发堆栈:", new Throwable("401触发堆栈追踪"));
Log.d("DINGDING", "当前Activity状态: isFinishing=" + isFinishing() + ", isDestroyed=" + isDestroyed());
// 检查Activity状态如果正在销毁则不处理
@@ -269,6 +277,16 @@ public abstract class BaseActivity<T extends ViewBinding, P extends IPresenter>
} catch (Exception e) {
e.printStackTrace();
}
LoadingProgressDialog progressDialog = mProgressLoadingDialog;
try {
if (progressDialog != null && mContext != null) {
mProgressLoadingDialog = null;
progressDialog.dismiss();
}
} catch (Exception e) {
e.printStackTrace();
}
}
//每个activity都需要创建Presenter
@@ -311,6 +329,7 @@ public abstract class BaseActivity<T extends ViewBinding, P extends IPresenter>
@Override
public void hideLoading() {
loadingDialog.dismiss();
}
@Override
@@ -353,6 +372,9 @@ public abstract class BaseActivity<T extends ViewBinding, P extends IPresenter>
protected LoadingDialog mLoadingDialog;
/**
* 普通加载loading
*/
public void showLoadingDialog() {
LoadingDialog dialog = mLoadingDialog;
if (dialog == null && mContext != null) {
@@ -375,6 +397,33 @@ public abstract class BaseActivity<T extends ViewBinding, P extends IPresenter>
}
}
/**
* 进度条加载loading
*/
protected LoadingProgressDialog mProgressLoadingDialog;
public void showProgressLoadingDialog(int progress) {
LoadingProgressDialog dialog = mProgressLoadingDialog;
if (dialog == null && mContext != null) {
dialog = new LoadingProgressDialog(mContext);
// 不可触摸取消
dialog.setCanceledOnTouchOutside(false);
// 强制取消关闭界面
dialog.setCancelable(true);
dialog.setOnCancelListener(dialog1 -> finish());
dialog.setProgress( progress);
mProgressLoadingDialog = dialog;
} else {
dialog.dismiss();
}
if (dialog != null && mContext != null) {
try {
dialog.show();
} catch (Exception e) {
e.printStackTrace();
}
}
}
@Override
public void onNetChange(int netModel) {
@@ -478,16 +527,34 @@ public abstract class BaseActivity<T extends ViewBinding, P extends IPresenter>
*
* @param title 标题
* @param hint 提示内容2
* @param content 内容
* @param touchOutsideCancel 弹窗类型
* @param cancelText 取消 文案
* @param confirmText 确定 文案
* @param click
*/
public void showEditDialog(String title, String hint, boolean touchOutsideCancel, String cancelText, String confirmText,
public void showEditDialog(String title,
String hint,
String content,
boolean touchOutsideCancel,
String cancelText,
String confirmText,
int inputType,
final OnDialogClick click) {
View view = getLayoutInflater().inflate(R.layout.public_dialog_input_text, null);
EditText editText = view.findViewById(R.id.et_input);
// EditText自动获取焦点
editText.requestFocus();
//设置输入类型
setEditInputType(editText,inputType);
editText.setHint(hint);
if(!TextUtils.isEmpty(content)){
editText.setText(content);
}
if (!TextUtils.isEmpty(content)) {
editText.setSelection(editText.getText().length());
}
setTextView(R.id.tv_title, title, view);
if (!TextUtils.isEmpty(confirmText) && !TextUtils.isEmpty(cancelText)) {
((TextView) view.findViewById(R.id.btnLeft)).setText(cancelText);
@@ -1035,7 +1102,8 @@ public abstract class BaseActivity<T extends ViewBinding, P extends IPresenter>
false, false, true,
title,
content,
"不允许", "允许",
getString(R.string.button_deny),
getString(R.string.button_allow),
new BaseFragment.OnDialogClick() {
@Override
public void onCancelClick() {
@@ -1123,4 +1191,77 @@ public abstract class BaseActivity<T extends ViewBinding, P extends IPresenter>
// 方法2通过Application检查如果有记录当前Activity
return MyApplication.getCurrentActivity() == this;
}
private void setEditInputType(EditText editText,int type){
switch (type){
case INPUT_TYPE_NUMBER:
//纯数字键盘
editText.setInputType(
InputType.TYPE_CLASS_NUMBER
);
editText.setFilters(new InputFilter[]{new InputFilter.LengthFilter(4)});
break;
case INPUT_TYPE_LETTER:
//只能输入字母
editText.setFilters(
new InputFilter[]{
(source,start,end,dest,dstart,dend)->{
if(source.toString()
.matches("[a-zA-Z]+")){
return source;
}
return "";
}
});
break;
case INPUT_TYPE_CHINESE:
//只能输入中文
editText.setFilters(
new InputFilter[]{
(source,start,end,dest,dstart,dend)->{
if(source.toString()
.matches("[\\u4e00-\\u9fa5]+")){
return source;
}
return "";
}
});
break;
case INPUT_TYPE_NUMBER_LETTER:
//数字+字母
editText.setFilters(
new InputFilter[]{
(source,start,end,dest,dstart,dend)->{
if(source.toString()
.matches("[a-zA-Z0-9]+")){
return source;
}
return "";
}
});
break;
case INPUT_TYPE_NORMAL:
editText.setFilters(new InputFilter[]{new InputFilter.LengthFilter(20)});
break;
default:
editText.setInputType(
InputType.TYPE_CLASS_TEXT
);
break;
}
}
}

View File

@@ -11,6 +11,8 @@ import android.content.Intent;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.os.Bundle;
import android.text.InputFilter;
import android.text.InputType;
import android.text.TextUtils;
import android.util.Log;
import android.view.Gravity;
@@ -20,6 +22,8 @@ import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
@@ -30,6 +34,7 @@ import androidx.core.app.ActivityCompat;
import androidx.fragment.app.Fragment;
import androidx.viewbinding.ViewBinding;
import com.ckkj.water.utils.show.ToastUtil;
import com.esafirm.imagepicker.features.ImagePicker;
import com.ckkj.water.AppConfig;
import com.ckkj.water.ConstantUtil;
@@ -70,6 +75,12 @@ public abstract class BaseFragment<T extends ViewBinding,P extends IPresenter> e
protected static final int REQUEST_EVENT_CODE_10002 = 10002;
protected static final int REQUEST_EVENT_CODE_10003 = 10003;
public static final int INPUT_TYPE_NORMAL = 0; // 默认
public static final int INPUT_TYPE_NUMBER = 1; // 数字
public static final int INPUT_TYPE_LETTER = 2; // 英文字母
public static final int INPUT_TYPE_CHINESE = 3; // 中文
public static final int INPUT_TYPE_NUMBER_LETTER = 4;//数字+字母
private static final AtomicBoolean isDialogShown = new AtomicBoolean(false); // 使用 AtomicBoolean 保证线程安全
@@ -90,6 +101,10 @@ public abstract class BaseFragment<T extends ViewBinding,P extends IPresenter> e
return EasyPermissions.hasPermissions(mContext, permission);
}
public boolean hasRecordPermission(String[] permission) {
return EasyPermissions.hasPermissions(mContext, permission);
}
/**
* 获取权限
*
@@ -108,7 +123,8 @@ public abstract class BaseFragment<T extends ViewBinding,P extends IPresenter> e
false, false,
title,
content,
"不允许", "允许",
getString(R.string.button_deny),
getString(R.string.button_allow),
new BaseFragment.OnDialogClick() {
@Override
public void onCancelClick() {
@@ -134,6 +150,50 @@ public abstract class BaseFragment<T extends ViewBinding,P extends IPresenter> e
});
}
/**
* 一次获取多个权限
*
* @param permis
* @param title
* @param content
* @param requestCode String... permis
*/
public void getMorePermissionRequst(String[] permis, String title, String content, int requestCode) {
if (EasyPermissions.hasPermissions(mContext, permis)) {
// 已有权限,不需要处理
return;
}
// 还没权限,弹自定义确认弹窗
showDialogtextInterBackKey(
null,
false,
false,
title,
content,
getString(R.string.button_deny),
getString(R.string.button_allow),
new BaseFragment.OnDialogClick() {
@Override
public void onCancelClick() {
}
@Override
public void onConfirmClick() {
showPermissionDialog(mContext.getResources().getDrawable(R.mipmap.img_permission_file),
true, title, content);
boolean shouldShowRationale = false;
for (String p : permis) {
if (ActivityCompat.shouldShowRequestPermissionRationale(mContext, p)) {
shouldShowRationale = true;
break;
}
}
// 使用 EasyPermissions 请求权限(系统决定是否弹系统框)
EasyPermissions.requestPermissions(mContext, content, requestCode, permis);
}
},false);
}
/**
* 判断Fragment是否真正对用户可见
*/
@@ -860,6 +920,202 @@ public abstract class BaseFragment<T extends ViewBinding,P extends IPresenter> e
});
}
/**
* +
*
* @param title 标题
* @param hint 提示内容2
* @param content 内容
* @param touchOutsideCancel 弹窗类型
* @param cancelText 取消 文案
* @param confirmText 确定 文案
* @param click
*/
public void showEditDialog(String title,
String hint,
String content,
boolean touchOutsideCancel,
String cancelText,
String confirmText,
int inputType,
final BaseActivity.OnDialogClick click) {
View view = getLayoutInflater().inflate(
R.layout.public_dialog_input_text,
null
);
EditText editText = view.findViewById(R.id.et_input);
//设置输入类型
setEditInputType(editText,inputType);
editText.setHint(hint);
if(!TextUtils.isEmpty(content)){
editText.setText(content);
editText.setSelection(content.length());
}
setTextView(R.id.tv_title,title,view);
if (!TextUtils.isEmpty(confirmText)
&& !TextUtils.isEmpty(cancelText)) {
((TextView)view.findViewById(R.id.btnLeft))
.setText(cancelText);
((TextView)view.findViewById(R.id.btnRight))
.setText(confirmText);
}
view.findViewById(R.id.btnLeft)
.setOnClickListener(v -> {
if(dialog!=null&&dialog.isShowing())
dialog.dismiss();
if(click!=null)
click.onCancelClick();
});
view.findViewById(R.id.btnRight)
.setOnClickListener(v -> {
String value=editText.getText()
.toString()
.trim();
if(TextUtils.isEmpty(value)){
ToastUtil.showShort(mContext,hint);
return;
}
if(dialog!=null&&dialog.isShowing())
dialog.dismiss();
if(click!=null)
click.onConfirmClisk(value);
});
AlertDialog.Builder builder;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
builder = new AlertDialog.Builder(
mContext,
AlertDialog.THEME_HOLO_LIGHT
);
} else {
builder = new AlertDialog.Builder(mContext);
}
builder.setInverseBackgroundForced(true);
builder.setView(view);
dialog = builder.show();
editText.requestFocus();
editText.postDelayed(() -> {
if (editText != null) {
InputMethodManager imm = (InputMethodManager) mContext.getSystemService(Context.INPUT_METHOD_SERVICE);
if (imm != null) {
imm.showSoftInput(editText, InputMethodManager.SHOW_IMPLICIT);
}
}
}, 200);
dialog.setCanceledOnTouchOutside(
touchOutsideCancel
);
try {
((View)dialog.getWindow()
.getDecorView()
.findViewById(R.id.contentDialog)
.getParent()
.getParent())
.setBackgroundColor(
getResources().getColor(
R.color.transparent
)
);
} catch (Exception e) {
e.printStackTrace();
}
}
private void setEditInputType(EditText editText,int type){
switch (type){
case INPUT_TYPE_NUMBER:
//纯数字键盘
editText.setInputType(
InputType.TYPE_CLASS_NUMBER
);
break;
case INPUT_TYPE_LETTER:
//只能输入字母
editText.setFilters(
new InputFilter[]{
(source,start,end,dest,dstart,dend)->{
if(source.toString()
.matches("[a-zA-Z]+")){
return source;
}
return "";
}
});
break;
case INPUT_TYPE_CHINESE:
//只能输入中文
editText.setFilters(
new InputFilter[]{
(source,start,end,dest,dstart,dend)->{
if(source.toString()
.matches("[\\u4e00-\\u9fa5]+")){
return source;
}
return "";
}
});
break;
case INPUT_TYPE_NUMBER_LETTER:
//数字+字母
editText.setFilters(
new InputFilter[]{
(source,start,end,dest,dstart,dend)->{
if(source.toString()
.matches("[a-zA-Z0-9]+")){
return source;
}
return "";
}
});
break;
default:
editText.setInputType(
InputType.TYPE_CLASS_TEXT
);
break;
}
}
/**
* 权限请求结果回调
*/

View File

@@ -1,66 +0,0 @@
package com.ckkj.water.base.entity;
import java.io.Serializable;
import java.util.List;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @author fengxiaoyang
* @date 2025/7/28
* @description TODO: 描述该类的作用
*/
@NoArgsConstructor
@Data
public class MineUserInfoBean implements Serializable {
/**
* userId : 2056543507514097665
* tenantId : 000000
* deptId : null
* userName : null
* nickName : 用户1779153155517
* userType : app_user
* email :
* phonenumber : 133****6054
* sex : 0
* avatar : null
* password : $2a$10$KsCb1Z1znyQgL7W.GoljuuVPctzZ7tS7obu8W2WkK5ydsejQOjRi2
* status : 0
* loginIp : 192.168.1.7
* loginDate : 2026-05-19 11:06:22
* remark : null
* createTime : 2026-05-19 09:12:36
* deptName : null
* roles : []
* roleIds : null
* postIds : null
* roleId : null
* oldPassword : null
*/
private String userId;
private String tenantId;
private Object deptId;
private Object userName;
private String nickName;
private String userType;
private String email;
private String phonenumber;
private String sex;
private Object avatar;
private String password;
private String status;
private String loginIp;
private String loginDate;
private Object remark;
private String createTime;
private Object deptName;
private Object roleIds;
private Object postIds;
private Object roleId;
private Object oldPassword;
private List<?> roles;
}

View File

@@ -30,12 +30,21 @@ public class CustomTypeFilterPopupView extends PartShadowPopupView implements Vi
private boolean mSelManual = false;
//是否选择了自动排程
private boolean mSelAuto = false;
private int mFilterType = -1;
public CustomTypeFilterPopupView(@NonNull Context context, OnClickListener listener) {
super(context);
this.mContext = context;
this.listener = listener;
}
public CustomTypeFilterPopupView(@NonNull Context context, OnClickListener listener, int filterType) {
super(context);
this.mContext = context;
this.listener = listener;
this.mFilterType = filterType;
}
public interface OnClickListener{
void callBack(boolean mSelManual,boolean mSelAuto);
}
@@ -59,7 +68,18 @@ public class CustomTypeFilterPopupView extends PartShadowPopupView implements Vi
tvAuto.setOnClickListener(this);
tvReset.setOnClickListener(this);
tvFinish.setOnClickListener(this);
tvManual.setSelected(false);
// 根据filterType设置初始选中状态
if (mFilterType == 0) {
// 排程
mSelAuto = true;
tvAuto.setTextColor(mContext.getColor(R.color.white));
tvAuto.setSelected(true);
} else if (mFilterType == 1) {
// 手动
mSelManual = true;
tvManual.setTextColor(mContext.getColor(R.color.white));
tvManual.setSelected(true);
}
}
@@ -68,25 +88,35 @@ public class CustomTypeFilterPopupView extends PartShadowPopupView implements Vi
switch (v.getId()){
case R.id.tv_manual:
if(mSelManual){
// 已选中,取消选中
mSelManual = false;
tvManual.setTextColor(mContext.getColor(R.color.color_zhu));
tvManual.setSelected(mSelManual);
tvManual.setSelected(false);
}else{
// 选中手动,同时取消自动
mSelManual = true;
mSelAuto = false;
tvManual.setTextColor(mContext.getColor(R.color.white));
tvManual.setSelected(mSelManual);
tvManual.setSelected(true);
tvAuto.setTextColor(mContext.getColor(R.color.color_zhu));
tvAuto.setSelected(false);
}
break;
case R.id.tv_auto:
if(mSelAuto){
// 已选中,取消选中
mSelAuto = false;
tvAuto.setTextColor(mContext.getColor(R.color.color_zhu));
tvAuto.setSelected(mSelAuto);
tvAuto.setSelected(false);
}else{
// 选中自动,同时取消手动
mSelAuto = true;
mSelManual = false;
tvAuto.setTextColor(mContext.getColor(R.color.white));
tvAuto.setSelected(mSelAuto);
tvAuto.setSelected(true);
tvManual.setTextColor(mContext.getColor(R.color.color_zhu));
tvManual.setSelected(false);
}
break;
@@ -95,15 +125,11 @@ public class CustomTypeFilterPopupView extends PartShadowPopupView implements Vi
mSelAuto = false;
tvManual.setTextColor(mContext.getColor(R.color.color_zhu));
tvAuto.setTextColor(mContext.getColor(R.color.color_zhu));
tvManual.setSelected(mSelManual);
tvAuto.setSelected(mSelAuto);
tvManual.setSelected(false);
tvAuto.setSelected(false);
break;
case R.id.tv_finish:
if(!mSelManual && !mSelAuto){
ToastUtil.showShort(mContext,mContext.getString(R.string.history_filter_type_toast));
return;
}
if(listener != null){
listener.callBack(mSelManual,mSelAuto);
this.dismiss();

View File

@@ -4,25 +4,41 @@ import static android.view.View.GONE;
import static android.view.View.VISIBLE;
import android.Manifest;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothManager;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.drawable.AnimationDrawable;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.ParcelUuid;
import android.text.TextUtils;
import android.util.Log;
import android.util.SparseArray;
import android.view.View;
import android.widget.ImageView;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
import androidx.core.content.ContextCompat;
import com.chad.library.adapter.base.BaseQuickAdapter;
import com.ckkj.water.ConstantUtil;
import com.ckkj.water.R;
import com.ckkj.water.base.BaseActivity;
import com.ckkj.water.custom.GridSpacingItemDecoration;
import com.ckkj.water.databinding.AddDeviceLayoutBinding;
import com.ckkj.water.device.adapter.BleScanDeviceAdapter;
import com.ckkj.water.device.mvp.DeviceContract;
import com.ckkj.water.device.mvp.DeviceImpl;
import com.ckkj.water.device.mvp.DevicePresenter;
import com.ckkj.water.index.entity.WaterDeviceEntity;
import com.ckkj.water.network.BaseBean;
import com.ckkj.water.utils.manager.ActivityManager;
import com.ckkj.water.utils.manager.ThemeManager;
import com.ckkj.water.utils.manager.WaterDeviceManager;
import com.ckkj.water.utils.show.ToastUtil;
import com.gyf.immersionbar.ImmersionBar;
import com.maning.mlkitscanner.scan.MNScanManager;
@@ -31,8 +47,17 @@ import com.maning.mlkitscanner.scan.callback.act.MNScanCallback;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.UUID;
import no.nordicsemi.android.support.v18.scanner.BluetoothLeScannerCompat;
import no.nordicsemi.android.support.v18.scanner.ScanCallback;
import no.nordicsemi.android.support.v18.scanner.ScanFilter;
import no.nordicsemi.android.support.v18.scanner.ScanRecord;
import no.nordicsemi.android.support.v18.scanner.ScanResult;
import no.nordicsemi.android.support.v18.scanner.ScanSettings;
import pub.devrel.easypermissions.EasyPermissions;
/**
@@ -40,6 +65,21 @@ import pub.devrel.easypermissions.EasyPermissions;
*/
public class AddDeviceActivity extends BaseActivity<AddDeviceLayoutBinding, DevicePresenter>
implements DeviceContract.DeviceView, EasyPermissions.PermissionCallbacks {
// 蓝牙相关
private BluetoothAdapter bluetoothAdapter;
private static final int REQUEST_ENABLE_BT = 1001;
private static final int REQUEST_BLUETOOTH_PERMISSION = 1002;
private List<BluetoothDevice> discoveredDevices = new ArrayList<>();
private AlertDialog deviceListDialog;
private String mUuid = "1775244d-6b43-439b-877c-060f2d9bed07";
private ScanCallback mScanCallback;
private boolean bluetoothReady = false;
private BleScanDeviceAdapter bleAdapter;
private List<WaterDeviceEntity> mDeviceList = new ArrayList<>();
private Set<String> discoveredMacSet = new HashSet<>();
private WaterDeviceManager waterDeviceManager;
@Override
public DevicePresenter createPresenter() {
return new DevicePresenter(new DeviceImpl());
@@ -49,6 +89,7 @@ public class AddDeviceActivity extends BaseActivity<AddDeviceLayoutBinding, Devi
@Override
public void initData(Bundle savedInstanceState) {
super.initData(savedInstanceState);
ActivityManager.addActivity(this,getClass().getSimpleName() + "_" + ConstantUtil.ADD_DEVICE_FLAG);
ImmersionBar.with(this)
.statusBarColor(R.color.mainBackgroundColor) // 设置状态栏颜色
@@ -56,37 +97,199 @@ public class AddDeviceActivity extends BaseActivity<AddDeviceLayoutBinding, Devi
.titleBar(viewBinding.rlTitle)
.init();
viewBinding.includedTitle.tvTitle.setText(R.string.add_device_title);
viewBinding.rvDevices.addItemDecoration(new GridSpacingItemDecoration(4, 10, true));
bleAdapter = new BleScanDeviceAdapter(mContext,R.layout.scan_ble_device_item,mDeviceList);
viewBinding.rvDevices.setAdapter(bleAdapter);
if(checkBluetoothPermissions()){
// 初始化蓝牙适配器
initBluetooth();
if (bluetoothReady) {
startBleScan();
}
}
// 启动帧动画
ImageView ivScanAnimation = viewBinding.ivScanAnimation;
if (ivScanAnimation.getDrawable() instanceof AnimationDrawable) {
AnimationDrawable animationDrawable = (AnimationDrawable) ivScanAnimation.getDrawable();
animationDrawable.start();
}
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
// 停止帧动画
ImageView ivScanAnimation = viewBinding.ivScanAnimation;
if (ivScanAnimation.getDrawable() instanceof AnimationDrawable) {
AnimationDrawable animationDrawable = (AnimationDrawable) ivScanAnimation.getDrawable();
if (animationDrawable.isRunning()) {
animationDrawable.stop();
viewBinding.ivScanAnimation.setVisibility(GONE);
viewBinding.imgDeviceItem.setVisibility(VISIBLE);
}
}
}
},3000);
initListener();
}
/**
* 初始化监听g
*/
private void initListener() {
setClick(viewBinding.includedTitle.imgBack);
setClick(viewBinding.tvScanAdd);
setClick(viewBinding.imgDeviceItem);
setClick(viewBinding.btnBleScan);
if(bleAdapter != null){
bleAdapter.setOnItemClickListener(new BaseQuickAdapter.OnItemClickListener() {
@Override
public void onItemClick(BaseQuickAdapter adapter, View view, int position) {
WaterDeviceEntity device = mDeviceList.get(position);
String deviceName = TextUtils.isEmpty(device.getDeviceName()) ?
"未知设备" : device.getDeviceName();
// 停止扫描
stopBleScan();
Bundle bundle = new Bundle();
bundle.putInt(ConstantUtil.ACTIVITY_NAVIGATE_FLAG,100);
bundle.putSerializable("ble_device_entity",mDeviceList.get(position));
goTo(mContext, SelectWifiActivity.class,bundle);
}
});
}
}
/**
* 开始 BLE 扫描
*/
private void startBleScan() {
BluetoothLeScannerCompat scanner = BluetoothLeScannerCompat.getScanner();
UUID SERVICE_UUID = UUID.fromString(mUuid);//1775244d-6b43-439b-877c-060f2d9bed07
ParcelUuid parcelUuid = new ParcelUuid(SERVICE_UUID);
ScanSettings settings = new ScanSettings.Builder()
.setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY)
.setReportDelay(0)
.build();
List<ScanFilter> filters = new ArrayList<>();
filters.add(new ScanFilter.Builder().setServiceUuid(parcelUuid).build());
// filters.add(new ScanFilter.Builder().setDeviceName("PROV_Water_01").build());
Log.e("TEST", "开始扫描");
mScanCallback = new ScanCallback() {
@Override
public void onScanResult(int callbackType, @NonNull ScanResult result) {
super.onScanResult(callbackType, result);
//Mac地址
String deviceAddress = result.getDevice().getAddress();
// 去重:已存在的设备不再添加
if (discoveredMacSet.contains(deviceAddress)) {//dc:da:0c:fa:2b:3a
return;
}
discoveredMacSet.add(deviceAddress);
WaterDeviceEntity bean = new WaterDeviceEntity();
ScanRecord record = result.getScanRecord();
SparseArray<byte[]> manufacturerData = record.getManufacturerSpecificData();
//设备名字
String deviceName = result.getScanRecord() != null ?
result.getScanRecord().getDeviceName() : "无名称";
bean.setDeviceName(deviceName);
bean.setMacAddress(deviceAddress);
mDeviceList.add(bean);
bleAdapter.notifyItemInserted(mDeviceList.size() - 1);
if(bleAdapter.getItemCount() != 0){
viewBinding.rvDevices.setVisibility(VISIBLE);
// 停止帧动画
ImageView ivScanAnimation = viewBinding.ivScanAnimation;
if (ivScanAnimation.getDrawable() instanceof AnimationDrawable) {
AnimationDrawable animationDrawable = (AnimationDrawable) ivScanAnimation.getDrawable();
if (animationDrawable.isRunning()) {
animationDrawable.stop();
}
viewBinding.ivScanAnimation.setVisibility(GONE);
}
}
}
@Override
public void onBatchScanResults(@NonNull List<ScanResult> results) {
super.onBatchScanResults(results);
Log.e("TEST", "批量结果: " + results.size() + " 个设备");
}
@Override
public void onScanFailed(int errorCode) {
super.onScanFailed(errorCode);
Log.e("TEST", "扫描失败: " + errorCode);
ToastUtil.showShort(mContext, "扫描失败,错误码: " + errorCode);
}
};
scanner.startScan(filters, settings, mScanCallback);
}
/**
* 停止 BLE 扫描
*/
private void stopBleScan() {
if (mScanCallback != null) {
BluetoothLeScannerCompat scanner = BluetoothLeScannerCompat.getScanner();
scanner.stopScan(mScanCallback);
Log.e("TEST", "停止扫描");
}
}
/**
* 初始化蓝牙适配器
*/
private void initBluetooth() {
BluetoothManager bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
if (bluetoothManager != null) {
bluetoothAdapter = bluetoothManager.getAdapter();
}
if (bluetoothAdapter == null) {
ToastUtil.showShort(mContext, "设备不支持蓝牙");
return;
}
try {
// 检查蓝牙是否开启
if (!bluetoothAdapter.isEnabled()) {
Log.e("TEST", "initBluetooth: 蓝牙未开启,请求开启");
Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
} else {
bluetoothReady = true;
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* 检查蓝牙权限
*/
private boolean checkBluetoothPermissions() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
String[] readPermission = new String[]{
Manifest.permission.BLUETOOTH_SCAN,
Manifest.permission.BLUETOOTH_CONNECT,
Manifest.permission.ACCESS_FINE_LOCATION
};
if (!hasRecordPermission(readPermission)) {
// 没有权限只在ACTION_DOWN时去申请
getMorePermissionRequst(readPermission,"蓝牙扫描权限申请",
"智能浇水需要您的授权,获取蓝牙权限添加设备",REQUEST_EVENT_CODE_10003);
return false;
}
} else {
// Android 12 以下需要位置权限才能扫描蓝牙
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
!= PackageManager.PERMISSION_GRANTED) {
requestPermissions(new String[]{
Manifest.permission.ACCESS_FINE_LOCATION
}, REQUEST_BLUETOOTH_PERMISSION);
return false;
}
}
return true;
}
private void setClick(View view) {
view.setOnClickListener(this::onClick);
}
@@ -97,12 +300,6 @@ public class AddDeviceActivity extends BaseActivity<AddDeviceLayoutBinding, Devi
finish();
break;
case R.id.img_device_item:
Bundle bundle = new Bundle();
bundle.putInt(ConstantUtil.ACTIVITY_NAVIGATE_FLAG,100);
goTo(mContext, SelectWifiActivity.class,bundle);
break;
case R.id.tv_scan_add:
//检测有无相机权限
String readPermission = Manifest.permission.CAMERA;
@@ -113,6 +310,48 @@ public class AddDeviceActivity extends BaseActivity<AddDeviceLayoutBinding, Devi
scanQrcode();
}
break;
case R.id.btn_ble_scan:
// 扫描蓝牙设备
break;
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == REQUEST_ENABLE_BT) {
if (resultCode == RESULT_OK) {
ToastUtil.showShort(mContext, "蓝牙已开启");
Log.e("BluetoothScan", "onActivityResult: 蓝牙已开启,开始扫描");
bluetoothReady = true;
startBleScan();
} else {
ToastUtil.showShort(mContext, "请开启蓝牙以扫描设备");
Log.e("BluetoothScan", "onActivityResult: 用户拒绝开启蓝牙");
}
}
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull @NotNull String[] permissions, @NonNull @NotNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this);
hidePermissionDialog();
if (requestCode == REQUEST_BLUETOOTH_PERMISSION) {
boolean allGranted = true;
for (int result : grantResults) {
if (result != PackageManager.PERMISSION_GRANTED) {
allGranted = false;
break;
}
}
if (allGranted) {
// 初始化蓝牙适配器
initBluetooth();
} else {
ToastUtil.showShort(mContext, "需要蓝牙权限才能扫描设备");
}
}
}
@@ -169,17 +408,13 @@ public class AddDeviceActivity extends BaseActivity<AddDeviceLayoutBinding, Devi
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull @NotNull String[] permissions, @NonNull @NotNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this);
}
@Override
public void onPermissionsGranted(int requestCode, @NonNull List<String> perms) {
hidePermissionDialog();
if (requestCode == REQUEST_EVENT_CODE_10001) {
scanQrcode();
}else if(requestCode == REQUEST_EVENT_CODE_10002){
}
}
@@ -189,7 +424,12 @@ public class AddDeviceActivity extends BaseActivity<AddDeviceLayoutBinding, Devi
}
@Override
public void addDeviceSuccess(BaseBean bean) {
public void addDeviceSuccess(WaterDeviceEntity bean) {
}
@Override
public void getDeviceDetailInfo(WaterDeviceEntity bean) {
}
@@ -204,7 +444,30 @@ public class AddDeviceActivity extends BaseActivity<AddDeviceLayoutBinding, Devi
}
@Override
public void turnOnOffDeviceSuccess(BaseBean bean) {
public void turnOnOffDeviceSuccess(BaseBean bean, String status) {
}
@Override
public void queryDeviceBindStatusSuccess(WaterDeviceEntity bean) {
}
@Override
public void queryDeviceWorkTimeSuccess(WaterDeviceEntity bean) {
}
@Override
protected void onDestroy() {
super.onDestroy();
// 停止扫描
stopBleScan();
// 断开蓝牙连接
if (waterDeviceManager != null) {
waterDeviceManager.disconnect().enqueue();
waterDeviceManager.close();
waterDeviceManager = null;
}
}
}

View File

@@ -3,10 +3,12 @@ package com.ckkj.water.device;
import static android.view.View.GONE;
import static android.view.View.VISIBLE;
import android.content.Intent;
import android.graphics.drawable.AnimationDrawable;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import com.ckkj.water.ConstantUtil;
import com.ckkj.water.R;
@@ -15,6 +17,9 @@ import com.ckkj.water.databinding.DeviceConnectLayoutBinding;
import com.ckkj.water.device.mvp.DeviceContract;
import com.ckkj.water.device.mvp.DeviceImpl;
import com.ckkj.water.device.mvp.DevicePresenter;
import com.ckkj.water.espBle.EspProvisionManager;
import com.ckkj.water.espBle.ProvisionCallback;
import com.ckkj.water.index.entity.WaterDeviceEntity;
import com.ckkj.water.network.BaseBean;
import com.ckkj.water.utils.manager.ActivityManager;
import com.ckkj.water.utils.show.ToastUtil;
@@ -30,6 +35,14 @@ public class DeviceConnectActivity extends BaseActivity<DeviceConnectLayoutBindi
private Handler handler = new Handler(Looper.getMainLooper());
private static final long ANIMATION_DURATION = 5000L; // 5秒
private String mWifiName;
private String mWifiPassword;
private WaterDeviceEntity mBleDeviceEntity;
private EspProvisionManager espProvisionManager;
private boolean isBleConnecting = false;
private boolean isBleConnected = false;
private boolean provisioningStarted = false;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@@ -38,6 +51,14 @@ public class DeviceConnectActivity extends BaseActivity<DeviceConnectLayoutBindi
@Override
public void initData(Bundle savedInstanceState) {
super.initData(savedInstanceState);
Bundle bundle = getIntent().getExtras();
if (bundle != null) {
mWifiName = bundle.getString("wifi_name", "");
mWifiPassword = bundle.getString("wifi_password", "");
mBleDeviceEntity = (WaterDeviceEntity) bundle.getSerializable("ble_device_entity");
}
ActivityManager.addActivity(this,getClass().getSimpleName() + "_" + ConstantUtil.ADD_DEVICE_FLAG);
ImmersionBar.with(this)
.statusBarColor(R.color.color_F9F9F9)
@@ -45,28 +66,183 @@ public class DeviceConnectActivity extends BaseActivity<DeviceConnectLayoutBindi
.titleBar(viewBinding.rlTitle)
.init();
viewBinding.includedTitle.tvTitle.setText(R.string.select_wifi_tip);
initEspProvision();
startConnectAnimation();
startProvisionWhenReady();
}
private void startConnectAnimation() {
viewBinding.tvConnectProgress.setText("正在配置网络");
if (animationDrawable != null && animationDrawable.isRunning()) {
animationDrawable.stop();
}
viewBinding.ivConnectAnimation.setImageResource(R.drawable.anim_connect_device);
animationDrawable = (AnimationDrawable) viewBinding.ivConnectAnimation.getDrawable();
if (animationDrawable != null) {
animationDrawable.start();
handler.postDelayed(() -> {
if (animationDrawable != null && animationDrawable.isRunning()) {
animationDrawable.stop();
}
viewBinding.linearConnectIng.setVisibility(VISIBLE);
viewBinding.linearSuccess.setVisibility(GONE);
}
private void stopConnectAnimation() {
handler.removeCallbacksAndMessages(null);
if (animationDrawable != null) {
animationDrawable.stop();
animationDrawable = null;
}
viewBinding.linearConnectIng.setVisibility(GONE);
viewBinding.linearSuccess.setVisibility(VISIBLE);
}
private void initEspProvision() {
espProvisionManager = EspProvisionManager.init(mContext).setCallback(new ProvisionCallback() {
@Override
public void onConnecting() {
isBleConnecting = true;
isBleConnected = false;
Log.i("TEST", "DeviceConnectActivity===== onConnecting");
}
@Override
public void onConnected() {
isBleConnecting = false;
isBleConnected = true;
startProvisionWhenReady();
Log.i("TEST", "DeviceConnectActivity===== onConnected设备连接成功");
}
@Override
public void onProvisioning(int progress) {
Log.i("TEST", "DeviceConnectActivity===== WIFI连接进度 == " + progress);
viewBinding.tvConnectProgress.setText("正在配置网络" + progress + "%");
if(progress == 100){
stopConnectAnimation();
}
viewBinding.linearConnectIng.setVisibility(GONE);
viewBinding.linearSuccess.setVisibility(VISIBLE);
new Handler().postDelayed(new Runnable() {
}
@Override
public void onSuccess(String deviceName, String deviceType) {
Log.i("TEST", "DeviceConnectActivity===== deviceName" + deviceName + "配网成功");
ToastUtil.showShort(mContext, deviceName + "配网成功");
handler.postDelayed(new Runnable() {
@Override
public void run() {
goTo(mContext, DeviceReNameActivity.class,null);
Bundle bundle = new Bundle();
mBleDeviceEntity.setWifiName(mWifiName);
mBleDeviceEntity.setWifiPassword(mWifiPassword);
bundle.putSerializable("ble_device_entity", mBleDeviceEntity);
goTo(mContext, DeviceReNameActivity.class, bundle);
finish();
}
},1000);
}, ANIMATION_DURATION);
}, 800);
}
@Override
public void onFailed(int errorCode, String message) {
isBleConnecting = false;
if (errorCode != 0) {
isBleConnected = espProvisionManager != null && espProvisionManager.isConnected();
}
Log.i("TEST", "DeviceConnectActivity===== errorCode == " + errorCode + " message == " + message);
ToastUtil.showShort(mContext, message);
//配网失败,返回到设备添加页面
returnToAddDeviceAfterFailed();
}
@Override
public void onDisconnected() {
isBleConnecting = false;
isBleConnected = false;
hideDialogLoading();
Log.i("TEST", "DeviceConnectActivity===== onDisconnected");
}
@Override
public void onWifiListReceived(String[] wifiList) {
Log.i("TEST", "DeviceConnectActivity===== onWifiListReceived" + wifiList.toString());
}
@Override
public void onWifiListFailed(String message) {
Log.i("TEST", "DeviceConnectActivity===== onWifiListFailed-Msg==" + message);
}
@Override
public void onProvisioningRejected() {
Log.i("TEST", "DeviceConnectActivity===== onProvisioningRejected");
}
});
}
private void returnToAddDeviceAfterFailed() {
hideDialogLoading();
handler.removeCallbacksAndMessages(null);
if (animationDrawable != null && animationDrawable.isRunning()) {
animationDrawable.stop();
animationDrawable = null;
}
provisioningStarted = false;
isBleConnecting = false;
isBleConnected = false;
if (espProvisionManager != null) {
espProvisionManager.setCallback(null);
espProvisionManager.disconnect();
}
Intent intent = new Intent(this, AddDeviceActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
startActivity(intent);
finish();
}
private void connectBleDevice() {
if (mBleDeviceEntity == null || espProvisionManager == null) {
ToastUtil.showShort(mContext, "\u8bbe\u5907\u8fde\u63a5\u672a\u521d\u59cb\u5316");
return;
}
if (isBleConnected || isBleConnecting) {
return;
}
espProvisionManager.connect(mBleDeviceEntity.getMacAddress(), mBleDeviceEntity.getDeviceName());
}
private void startProvisionWhenReady() {
if (provisioningStarted || espProvisionManager == null) {
return;
}
isBleConnected = espProvisionManager.isConnected();
if (isBleConnected) {
provisionWifi();
return;
}
if (!isBleConnecting) {
connectBleDevice();
}
}
private void provisionWifi() {
if (provisioningStarted) {
return;
}
if (espProvisionManager == null) {
ToastUtil.showShort(mContext, "设备连接未初始化");
return;
}
if (!espProvisionManager.isConnected()) {
startProvisionWhenReady();
return;
}
provisioningStarted = true;
espProvisionManager.provisionWifi(mWifiName, mWifiPassword);
}
@Override
@@ -76,6 +252,10 @@ public class DeviceConnectActivity extends BaseActivity<DeviceConnectLayoutBindi
if (animationDrawable != null && animationDrawable.isRunning()) {
animationDrawable.stop();
}
if (espProvisionManager != null) {
espProvisionManager.disconnect();
espProvisionManager.setCallback(null);
}
}
@Override
@@ -99,7 +279,12 @@ public class DeviceConnectActivity extends BaseActivity<DeviceConnectLayoutBindi
}
@Override
public void addDeviceSuccess(BaseBean bean) {
public void addDeviceSuccess(WaterDeviceEntity bean) {
}
@Override
public void getDeviceDetailInfo(WaterDeviceEntity bean) {
}
@@ -114,7 +299,17 @@ public class DeviceConnectActivity extends BaseActivity<DeviceConnectLayoutBindi
}
@Override
public void turnOnOffDeviceSuccess(BaseBean bean) {
public void turnOnOffDeviceSuccess(BaseBean bean, String status) {
}
@Override
public void queryDeviceBindStatusSuccess(WaterDeviceEntity bean) {
}
@Override
public void queryDeviceWorkTimeSuccess(WaterDeviceEntity bean) {
}
}

View File

@@ -1,26 +1,44 @@
package com.ckkj.water.device;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.text.TextUtils;
import android.view.View;
import androidx.annotation.Nullable;
import com.chad.library.adapter.base.BaseQuickAdapter;
import com.ckkj.water.EventMessage;
import com.ckkj.water.R;
import com.ckkj.water.base.BaseActivity;
import com.ckkj.water.base.BaseFragment;
import com.ckkj.water.custom.GridSpacingItemDecoration;
import com.ckkj.water.custom.view.CustomAttachPopup;
import com.ckkj.water.custom.view.CustomBubbleAttachPopup;
import com.ckkj.water.databinding.DeviceControlLayoutBinding;
import com.ckkj.water.device.adapter.DeviceTimeSelectAdapter;
import com.ckkj.water.device.mvp.DeviceContract;
import com.ckkj.water.device.mvp.DeviceImpl;
import com.ckkj.water.device.mvp.DevicePresenter;
import com.ckkj.water.index.entity.WaterDeviceEntity;
import com.ckkj.water.network.BaseBean;
import com.ckkj.water.utils.FastClickUtils;
import com.ckkj.water.utils.manager.PowerIconManage;
import com.ckkj.water.utils.manager.ThemeManager;
import com.ckkj.water.utils.show.ToastUtil;
import com.gyf.immersionbar.ImmersionBar;
import com.lxj.xpopup.XPopup;
import com.lxj.xpopup.core.BasePopupView;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import de.greenrobot.event.Subscribe;
import de.greenrobot.event.ThreadMode;
/**
* 设备控制页面
@@ -28,8 +46,37 @@ import java.util.List;
public class DeviceControlActivity extends BaseActivity<DeviceControlLayoutBinding, DevicePresenter>
implements DeviceContract.DeviceView {
private static final long DEVICE_DETAIL_POLL_INTERVAL_MS = 10_000L;
private List<String> mTimeList = new ArrayList<>();
private WaterDeviceEntity mDeviceEntity;
private WaterDeviceEntity mRemoteDeviceEntity;
private DeviceTimeSelectAdapter mAdapter;
//用户自定义的浇水时长
private int mCustomDuration = 0;
private final Handler mProgressHandler = new Handler(Looper.getMainLooper());
private final Handler mDeviceDetailPollHandler = new Handler(Looper.getMainLooper());
private boolean mIsDeviceDetailPolling;
private long mWorkStartTime = 0L;
private long mWorkEndTime = 0L;
private boolean mHasRefreshAfterWorkFinished = false;
private final Runnable mWorkProgressRunnable = new Runnable() {
@Override
public void run() {
updateWorkProgress();
}
};
private final Runnable mDeviceDetailPollRunnable = new Runnable() {
@Override
public void run() {
if (!mIsDeviceDetailPolling) {
return;
}
if (mDeviceEntity != null && !TextUtils.isEmpty(mDeviceEntity.getDeviceNo())) {
mPresenter.getDeviceDetailInfo(mDeviceEntity.getDeviceNo());
}
mDeviceDetailPollHandler.postDelayed(this, DEVICE_DETAIL_POLL_INTERVAL_MS);
}
};
@Override
public DevicePresenter createPresenter() {
return new DevicePresenter(new DeviceImpl());
@@ -38,6 +85,22 @@ public class DeviceControlActivity extends BaseActivity<DeviceControlLayoutBindi
@Override
public void initData(Bundle savedInstanceState) {
super.initData(savedInstanceState);
Bundle bundle = getIntent().getExtras();
if(bundle != null){
mDeviceEntity = (WaterDeviceEntity) bundle.getSerializable("device_info");
if(mDeviceEntity != null){
showLoadingDialog();
//查询设备详情
mPresenter.getDeviceDetailInfo(mDeviceEntity.getDeviceNo());
//查询设备当前工作进度
if(mDeviceEntity.getWorkStatus().equals("1")){
mPresenter.getDeviceWorkProgress(mDeviceEntity.getDeviceNo());
}
viewBinding.includedTitle.tvTitle.setText(mDeviceEntity.getDeviceName());
updateDeviceStatus(mDeviceEntity);
}
}
mTimeList.add("1min");
mTimeList.add("2min");
mTimeList.add("3min");
@@ -51,25 +114,66 @@ public class DeviceControlActivity extends BaseActivity<DeviceControlLayoutBindi
mTimeList.add("3h");
mTimeList.add("4h");
ImmersionBar.with(this)
.statusBarColor(R.color.mainBackgroundColor) // 设置状态栏颜色
.statusBarDarkFont(true) // 设置状态栏字体为黑色
.statusBarDarkFont(ThemeManager.isAppThemeLight(mContext)) // 白色状态栏图标
.navigationBarColor(R.color.mainBackgroundColor)
.titleBar(viewBinding.rlTitle)
.init();
viewBinding.includedTitle.tvTitle.setText("设备名称");
viewBinding.includedTitle.imgSetting.setVisibility(View.VISIBLE);
// viewBinding.includedTitle.imgSetting.setImageDrawable(getDrawable(R.mipmap.device_ctrl_setting));
mAdapter = new DeviceTimeSelectAdapter(mContext,R.layout.device_work_time_item,mTimeList);
viewBinding.rvTimeList.setAdapter(mAdapter);
viewBinding.rvTimeList.addItemDecoration(new GridSpacingItemDecoration(4, 10, true));
mAdapter.setOnItemClickListener(new BaseQuickAdapter.OnItemClickListener() {
@Override
public void onItemClick(BaseQuickAdapter adapter, View view, int position) {
//此时处于工作中,不可点击
if(mDeviceEntity.getWorkStatus().equals("1")){
ToastUtil.showShort(mContext,getString(R.string.tips_device_working_stop_task));
return;
}
mAdapter.setOnSelPosition(position);
mCustomDuration = 0;
viewBinding.tvWorkDuartion.setHint(getString(R.string.device_custom_work_time));
viewBinding.tvWorkDuartion.setText("");
}
});
//用户自定义时间
if(mCustomDuration == 0){
viewBinding.tvWorkDuartion.setHint(getString(R.string.device_custom_work_time));
}
initListener();
}
private void updateDeviceStatus(WaterDeviceEntity entity) {
if(entity.getStatus().equals("1") || entity.getStatus().equals("2")){
if(entity.getWorkStatus().equals("1")){
viewBinding.tvDeviceStatus.setText(getString(R.string.device_status_working));
viewBinding.tvDeviceStatus.setTextColor(mContext.getResources().getColor(R.color.color_zhu));
viewBinding.tvConfirm.setText(getString(R.string.device_control_stop));
}else{
viewBinding.tvDeviceStatus.setText(getString(R.string.device_status_not_working));
viewBinding.tvDeviceStatus.setTextColor(mContext.getResources().getColor(R.color.color_999999));
viewBinding.tvConfirm.setText(getString(R.string.device_control_start));
stopWorkProgressUpdate();
updateProgressView(0);
}
viewBinding.linearWifi.setBackground(mContext.getResources().getDrawable(R.drawable.shape_device_ctrl_green_cor12));
viewBinding.imgWifiLogo.setImageResource(R.mipmap.icon_ctrl_wifi_white);
}else{
viewBinding.tvDeviceStatus.setText(getString(R.string.device_status_offline));
viewBinding.tvDeviceStatus.setTextColor(mContext.getResources().getColor(R.color.color_E60000));
viewBinding.tvConfirm.setEnabled(false);
viewBinding.tvConfirm.setTextColor(mContext.getResources().getColor(R.color.color_999999));
viewBinding.tvConfirm.setBackgroundResource((R.drawable.shape_gray_button_bg_enable));
viewBinding.linearWifi.setBackground(mContext.getResources().getDrawable(R.drawable.shape_device_ctrl_white_cor12));
viewBinding.imgWifiLogo.setImageResource(R.mipmap.icon_ctrl_wifi_green);
stopWorkProgressUpdate();
updateProgressView(0);
}
viewBinding.tvDeviceUpdateTime.setText(getString(R.string.update_time) + entity.getPowerLevelUpdatatime());
}
private void initListener() {
setClick(viewBinding.includedTitle.imgBack);
setClick(viewBinding.includedTitle.imgSetting);
@@ -77,6 +181,7 @@ public class DeviceControlActivity extends BaseActivity<DeviceControlLayoutBindi
setClick(viewBinding.linearWifi);
setClick(viewBinding.linearBat);
setClick(viewBinding.tvConfirm);
setClick(viewBinding.tvWorkDuartion);
}
private void setClick(View view) {
@@ -90,11 +195,27 @@ public class DeviceControlActivity extends BaseActivity<DeviceControlLayoutBindi
break;
case R.id.img_setting:
goTo(mContext, DeviceSettingsActivity.class,null);
Bundle bundle = new Bundle();
bundle.putSerializable("device_entity",mDeviceEntity);
goToForResult(mContext, DeviceSettingsActivity.class,REQUEST_EVENT_CODE_10002,bundle);
break;
case R.id.linear_bt:
showDialogtext(null, false, false, true,
getString(R.string.tip_text),
getString(R.string.reset_device_provision),
getString(R.string.cancel_text),
getString(R.string.confirm_text),
new BaseFragment.OnDialogClick() {
@Override
public void onCancelClick() {
}
@Override
public void onConfirmClick() {
}
});
break;
case R.id.linear_wifi:
@@ -107,16 +228,210 @@ public class DeviceControlActivity extends BaseActivity<DeviceControlLayoutBindi
.isDestroyOnDismiss(true) //对于只使用一次的弹窗,推荐设置这个
.atView(viewBinding.linearBat)
.hasShadowBg(false) // 去掉半透明背景
.asCustom(new CustomBubbleAttachPopup(mContext,"设备电量:40% 更新时间: 05- 11 18:00"))
.asCustom(new CustomBubbleAttachPopup(mContext,getString(R.string.device_battery)+
mDeviceEntity.getPowerLevel() + "%" +
getString(R.string.update_time) + mDeviceEntity.getPowerLevelUpdatatime()))
.show();
break;
case R.id.tv_work_duartion:
//此时处于工作中,不可点击
if(mDeviceEntity.getWorkStatus().equals("1")){
ToastUtil.showShort(mContext,getString(R.string.tips_device_working_stop_task));
return;
}
inputDuration(mCustomDuration);
break;
case R.id.tv_confirm:
showCenterTipDialog(R.mipmap.icon_dialog_success,"开始浇水");
handleDeviceSwitch();
break;
}
}
/**
* 输入浇水时间
* @param currentDuration
*/
private void inputDuration(int currentDuration) {
showEditDialog(getString(R.string.device_work_times_title),
getString(R.string.input_water_plan_time),
currentDuration == 0 ? "" : currentDuration + "",
true,
getString(R.string.cancel_text),
getString(R.string.confirm_text),
INPUT_TYPE_NUMBER,
new BaseActivity.OnDialogClick() {
@Override
public void onCancelClick() {}
@Override
public void onConfirmClisk() {}
@Override
public void onConfirmClisk(String content) {
if (Integer.parseInt(content) <= 0) {
ToastUtil.showShort(mContext, getString(R.string.input_water_plan_time_error));
return;
}
viewBinding.tvWorkDuartion.setText(content);
mCustomDuration = Integer.parseInt(content);
if(mAdapter != null){
mAdapter.setOnSelPosition(-1);
}
}
@Override
public void onView1Click() {
}
});
}
/**
* 将时间字符串转换为分钟数
*
* 1min -> 1
* 10min -> 10
* 1h -> 60
* 2h -> 120
*
* @param timeValue 时间字符串
* @return 分钟数
*/
public static int convertToMinutes(String timeValue) {
if (TextUtils.isEmpty(timeValue)) {
return 0;
}
try {
if (timeValue.endsWith("min")) {
return Integer.parseInt(
timeValue.substring(0, timeValue.length() - 3)
);
}
if (timeValue.endsWith("h")) {
return Integer.parseInt(
timeValue.substring(0, timeValue.length() - 1)
) * 60;
}
} catch (Exception e) {
e.printStackTrace();
}
return 0;
}
/**
* 处理设备开关操作
*/
private void handleDeviceSwitch() {
if (mDeviceEntity == null) {
return;
}
// 检查设备在线状态
if (!mDeviceEntity.getStatus().equals("1") && !mDeviceEntity.getStatus().equals("2")) {
ToastUtil.showShort(mContext, getString(R.string.device_offline_tip));
return;
}
boolean isCurrentlyWorking = mDeviceEntity.getWorkStatus().equals("1");
// 开启浇水时,必须选择时长
if (!isCurrentlyWorking) {
if (mCustomDuration <= 0 && mAdapter.getmSelPostion() < 0) {
ToastUtil.showShort(mContext, getString(R.string.select_watering_duration));
return;
}
}
// 防止快速点击
if (!FastClickUtils.onclickTimes()) {
return;
}
// 显示加载状态
showLoadingDialog();
String newStatus = isCurrentlyWorking ? "0" : "1";
int duration = 0;
// 只有开启浇水时才计算时长
if (!isCurrentlyWorking) {
duration = mCustomDuration > 0 ? mCustomDuration
: convertToMinutes(mTimeList.get(mAdapter.getmSelPostion()));
}
mPresenter.switchDeviceWork(mDeviceEntity, newStatus, duration);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(resultCode == RESULT_OK){
switch (requestCode){
case REQUEST_EVENT_CODE_10002:
mDeviceEntity = (WaterDeviceEntity) data.getSerializableExtra("device_entity");
viewBinding.includedTitle.tvTitle.setText(mDeviceEntity.getDeviceName());
break;
}
}
}
@Subscribe(threadMode = ThreadMode.MainThread)
public void onGetMessage(EventMessage message) {
switch (message.msg){
case EventMessage.ACTIVITY_FINISH:
finish();
break;
}
}
/**
* 获取设备详情成功
* @param bean
*/
@Override
public void getDeviceDetailInfo(WaterDeviceEntity bean) {
hideDialogLoading();
viewBinding.imgBatStatus.setImageResource(PowerIconManage.getInstance().
getPowerVerIcon(Integer.parseInt(bean.getPowerLevel())));
mDeviceEntity = bean;
updateDeviceStatus( bean);
}
/**
* 开关设备成功
* @param bean
* @param status
*/
@Override
public void turnOnOffDeviceSuccess(BaseBean bean, String status) {
hideDialogLoading();
mDeviceEntity.setWorkStatus(status);
mCustomDuration = 0;
mAdapter.setOnSelPosition(-1);
viewBinding.tvWorkDuartion.setText("");
if(status.equals("0")){
showCenterTipDialog(R.mipmap.icon_dialog_success,getString(R.string.end_watering));
viewBinding.tvConfirm.setText(getString(R.string.start_watering));
stopWorkProgressUpdate();
updateProgressView(0);
}else{
showCenterTipDialog(R.mipmap.icon_dialog_success,getString(R.string.start_watering));
viewBinding.tvConfirm.setText(getString(R.string.end_watering));
mPresenter.getDeviceWorkProgress(mDeviceEntity.getDeviceNo());
}
//开关设备之后,更新一下当前设备状态
mPresenter.getDeviceDetailInfo(mDeviceEntity.getDeviceNo());
}
@Override
public int getLayoutResId(Bundle savedInstanceState) {
return 0;
@@ -124,7 +439,123 @@ public class DeviceControlActivity extends BaseActivity<DeviceControlLayoutBindi
@Override
public void showError(String message) {
hideDialogLoading();
ToastUtil.showShort(mContext,message);
}
/**
* 查询到设备目前的工作时间,控制进度条的展示
* @param bean
*/
@Override
public void queryDeviceWorkTimeSuccess(WaterDeviceEntity bean) {
if (bean == null || TextUtils.isEmpty(bean.getStartTime()) || TextUtils.isEmpty(bean.getEndTime())) {
stopWorkProgressUpdate();
updateProgressView(0);
return;
}
mWorkStartTime = parseWorkTime(bean.getStartTime());
mWorkEndTime = parseWorkTime(bean.getEndTime());
mHasRefreshAfterWorkFinished = false;
if (mWorkStartTime <= 0 || mWorkEndTime <= mWorkStartTime) {
stopWorkProgressUpdate();
updateProgressView(0);
return;
}
updateWorkProgress();
//"startTime": "2026-07-06 16:35:00",
//"endTime": "2026-07-06 16:37:00"
//bean.getStartTime(),bean.getEndTime(),这两个字段。
//Todo 根据以上开始时间和结束时间以及当前时间计算进度条的进度viewBinding.progressWork,做到实时更新。
}
private long parseWorkTime(String time) {
try {
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA);
Date date = format.parse(time);
return date == null ? 0L : date.getTime();
} catch (ParseException e) {
e.printStackTrace();
}
return 0L;
}
private void updateWorkProgress() {
long now = System.currentTimeMillis();
int progress;
if (now <= mWorkStartTime) {
progress = 0;
} else if (now >= mWorkEndTime) {
progress = 100;
} else {
progress = (int) ((now - mWorkStartTime) * 100 / (mWorkEndTime - mWorkStartTime));
}
updateProgressView(progress);
mProgressHandler.removeCallbacks(mWorkProgressRunnable);
if (progress < 100 && mDeviceEntity != null && "1".equals(mDeviceEntity.getWorkStatus())) {
mProgressHandler.postDelayed(mWorkProgressRunnable, 1000);
} else if (progress >= 100 && !mHasRefreshAfterWorkFinished
&& mDeviceEntity != null && !TextUtils.isEmpty(mDeviceEntity.getDeviceNo())) {
mHasRefreshAfterWorkFinished = true;
ToastUtil.showShort(mContext,"任务结束");
showLoadingDialog();
mProgressHandler.postDelayed(new Runnable() {
@Override
public void run() {
if (mDeviceEntity != null && !TextUtils.isEmpty(mDeviceEntity.getDeviceNo())) {
mPresenter.getDeviceDetailInfo(mDeviceEntity.getDeviceNo());
}
}
}, 1500);
}
}
private void updateProgressView(int progress) {
viewBinding.progressWork.setProgress(progress);
viewBinding.tvProgressPercent.setText(getString(R.string.device_work_progress_title) + progress + "%");
}
private void stopWorkProgressUpdate() {
mProgressHandler.removeCallbacksAndMessages(null);
mWorkStartTime = 0L;
mWorkEndTime = 0L;
}
private void startDeviceDetailPolling() {
mIsDeviceDetailPolling = true;
mDeviceDetailPollHandler.removeCallbacks(mDeviceDetailPollRunnable);
mDeviceDetailPollHandler.postDelayed(mDeviceDetailPollRunnable, DEVICE_DETAIL_POLL_INTERVAL_MS);
}
private void stopDeviceDetailPolling() {
mIsDeviceDetailPolling = false;
mDeviceDetailPollHandler.removeCallbacks(mDeviceDetailPollRunnable);
}
@Override
protected void onResume() {
super.onResume();
startDeviceDetailPolling();
}
@Override
protected void onPause() {
stopDeviceDetailPolling();
super.onPause();
}
@Override
protected void onDestroy() {
stopWorkProgressUpdate();
stopDeviceDetailPolling();
super.onDestroy();
}
@Override
@@ -133,10 +564,12 @@ public class DeviceControlActivity extends BaseActivity<DeviceControlLayoutBindi
}
@Override
public void addDeviceSuccess(BaseBean bean) {
public void addDeviceSuccess(WaterDeviceEntity bean) {
}
@Override
public void editDeviceInfoSuccess(BaseBean bean) {
@@ -147,8 +580,11 @@ public class DeviceControlActivity extends BaseActivity<DeviceControlLayoutBindi
}
@Override
public void turnOnOffDeviceSuccess(BaseBean bean) {
public void queryDeviceBindStatusSuccess(WaterDeviceEntity bean) {
}
}

View File

@@ -9,7 +9,9 @@ import com.ckkj.water.databinding.DeviceInfoLayoutBinding;
import com.ckkj.water.device.mvp.DeviceContract;
import com.ckkj.water.device.mvp.DeviceImpl;
import com.ckkj.water.device.mvp.DevicePresenter;
import com.ckkj.water.index.entity.WaterDeviceEntity;
import com.ckkj.water.network.BaseBean;
import com.ckkj.water.utils.manager.ThemeManager;
import com.gyf.immersionbar.ImmersionBar;
/**
@@ -17,6 +19,9 @@ import com.gyf.immersionbar.ImmersionBar;
*/
public class DeviceInfoActivity extends BaseActivity<DeviceInfoLayoutBinding, DevicePresenter>
implements DeviceContract.DeviceView {
private WaterDeviceEntity mDeviceEntity;
@Override
public DevicePresenter createPresenter() {
return new DevicePresenter(new DeviceImpl());
@@ -25,10 +30,17 @@ public class DeviceInfoActivity extends BaseActivity<DeviceInfoLayoutBinding, De
@Override
public void initData(Bundle savedInstanceState) {
super.initData(savedInstanceState);
Bundle bundle = getIntent().getExtras();
if(bundle != null){
mDeviceEntity = (WaterDeviceEntity) bundle.getSerializable("device_entity");
viewBinding.tvDevCode.setText(mDeviceEntity.getDeviceNo());
viewBinding.tvDevMod.setText(mDeviceEntity.getDeviceEm());
viewBinding.tvDeviceSerial.setText(mDeviceEntity.getDeviceSn());
viewBinding.tvDevVersion.setText(mDeviceEntity.getFwVer());
}
ImmersionBar.with(this)
.statusBarColor(R.color.white) // 设置状态栏颜色
.statusBarDarkFont(true) // 设置状态栏字体为黑色
.statusBarDarkFont(ThemeManager.isAppThemeLight(mContext)) // 白色状态栏图标
.navigationBarColor(R.color.mainBackgroundColor)
.titleBar(viewBinding.rlTitle)
.init();
viewBinding.includedTitle.tvTitle.setText(R.string.device_setting_info);
@@ -67,7 +79,12 @@ public class DeviceInfoActivity extends BaseActivity<DeviceInfoLayoutBinding, De
}
@Override
public void addDeviceSuccess(BaseBean bean) {
public void addDeviceSuccess(WaterDeviceEntity bean) {
}
@Override
public void getDeviceDetailInfo(WaterDeviceEntity bean) {
}
@@ -82,7 +99,17 @@ public class DeviceInfoActivity extends BaseActivity<DeviceInfoLayoutBinding, De
}
@Override
public void turnOnOffDeviceSuccess(BaseBean bean) {
public void turnOnOffDeviceSuccess(BaseBean bean, String status) {
}
@Override
public void queryDeviceBindStatusSuccess(WaterDeviceEntity bean) {
}
@Override
public void queryDeviceWorkTimeSuccess(WaterDeviceEntity bean) {
}
}

View File

@@ -8,10 +8,12 @@ import android.view.View;
import com.ckkj.water.ConstantUtil;
import com.ckkj.water.R;
import com.ckkj.water.base.BaseActivity;
import com.ckkj.water.base.BaseFragment;
import com.ckkj.water.databinding.SetDeviceNameLayoutBinding;
import com.ckkj.water.device.mvp.DeviceContract;
import com.ckkj.water.device.mvp.DeviceImpl;
import com.ckkj.water.device.mvp.DevicePresenter;
import com.ckkj.water.index.entity.WaterDeviceEntity;
import com.ckkj.water.network.BaseBean;
import com.ckkj.water.utils.manager.ActivityManager;
import com.ckkj.water.utils.show.ToastUtil;
@@ -22,6 +24,11 @@ import com.gyf.immersionbar.ImmersionBar;
*/
public class DeviceReNameActivity extends BaseActivity<SetDeviceNameLayoutBinding, DevicePresenter>
implements DeviceContract.DeviceView {
private String mWifiName;
private String mWifiPassword;
private WaterDeviceEntity mBleDeviceEntity;
@Override
public DevicePresenter createPresenter() {
return new DevicePresenter(new DeviceImpl());
@@ -30,6 +37,15 @@ public class DeviceReNameActivity extends BaseActivity<SetDeviceNameLayoutBindin
@Override
public void initData(Bundle savedInstanceState) {
super.initData(savedInstanceState);
Bundle bundle = getIntent().getExtras();
if (bundle != null) {
mBleDeviceEntity = (WaterDeviceEntity) bundle.getSerializable("ble_device_entity");
if(mBleDeviceEntity != null){
mWifiName = mBleDeviceEntity.getWifiName();
mWifiPassword = mBleDeviceEntity.getWifiPassword();
}
}
ImmersionBar.with(this)
.statusBarColor(R.color.color_F9F9F9) // 设置状态栏颜色
.statusBarDarkFont(true) // 设置状态栏字体为黑色
@@ -59,10 +75,11 @@ public class DeviceReNameActivity extends BaseActivity<SetDeviceNameLayoutBindin
ToastUtil.showShort(mContext,getString(R.string.input_device_name_hint));
return;
}
String deviceName = viewBinding.etDeviceName.getText().toString().trim();
// ToastUtil.showShort(mContext,"名称保存成功");
// goTo(mContext,DeviceControlActivity.class,null);
showLoadingDialog();
mPresenter.addDevice();
mPresenter.addDevice(deviceName,mWifiName,mWifiPassword,mBleDeviceEntity);
break;
}
}
@@ -72,19 +89,26 @@ public class DeviceReNameActivity extends BaseActivity<SetDeviceNameLayoutBindin
* @param bean
*/
@Override
public void addDeviceSuccess(BaseBean bean) {
public void addDeviceSuccess(WaterDeviceEntity bean) {
hideDialogLoading();
ToastUtil.showShort(mContext,"设备保存成功");
ToastUtil.showShort(mContext,getString(R.string.device_save_success));
ActivityManager.removeActivityByTag(ConstantUtil.ADD_DEVICE_FLAG);
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
goTo(mContext,DeviceControlActivity.class,null);
Bundle bundle = new Bundle();
bundle.putSerializable("device_info",bean);
goTo(mContext,DeviceControlActivity.class,bundle);
finish();
}
},800);
}
@Override
public void getDeviceDetailInfo(WaterDeviceEntity bean) {
}
@Override
public int getLayoutResId(Bundle savedInstanceState) {
@@ -93,7 +117,22 @@ public class DeviceReNameActivity extends BaseActivity<SetDeviceNameLayoutBindin
@Override
public void showError(String message) {
hideDialogLoading();
showDialogtext(null, false, false, false,
getString(R.string.tip_text),
message,
null,
getString(R.string.confirm_text),
new BaseFragment.OnDialogClick() {
@Override
public void onCancelClick() {
}
@Override
public void onConfirmClick() {
finish();
}
});
}
@Override
@@ -113,7 +152,17 @@ public class DeviceReNameActivity extends BaseActivity<SetDeviceNameLayoutBindin
}
@Override
public void turnOnOffDeviceSuccess(BaseBean bean) {
public void turnOnOffDeviceSuccess(BaseBean bean, String status) {
}
@Override
public void queryDeviceBindStatusSuccess(WaterDeviceEntity bean) {
}
@Override
public void queryDeviceWorkTimeSuccess(WaterDeviceEntity bean) {
}
}

View File

@@ -2,11 +2,13 @@ package com.ckkj.water.device;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.view.View;
import androidx.annotation.Nullable;
import com.ckkj.water.ConstantUtil;
import com.ckkj.water.EventMessage;
import com.ckkj.water.R;
import com.ckkj.water.base.BaseActivity;
import com.ckkj.water.base.BaseFragment;
@@ -14,15 +16,21 @@ import com.ckkj.water.databinding.DeviceSettingsLayoutBinding;
import com.ckkj.water.device.mvp.DeviceContract;
import com.ckkj.water.device.mvp.DeviceImpl;
import com.ckkj.water.device.mvp.DevicePresenter;
import com.ckkj.water.index.entity.WaterDeviceEntity;
import com.ckkj.water.network.BaseBean;
import com.ckkj.water.utils.manager.ThemeManager;
import com.ckkj.water.utils.show.ToastUtil;
import com.gyf.immersionbar.ImmersionBar;
import de.greenrobot.event.EventBus;
/**
* 设备控制页面
*/
public class DeviceSettingsActivity extends BaseActivity<DeviceSettingsLayoutBinding, DevicePresenter>
implements DeviceContract.DeviceView {
private WaterDeviceEntity mDeviceEntity;
@Override
public DevicePresenter createPresenter() {
return new DevicePresenter(new DeviceImpl());
@@ -31,10 +39,16 @@ public class DeviceSettingsActivity extends BaseActivity<DeviceSettingsLayoutBin
@Override
public void initData(Bundle savedInstanceState) {
super.initData(savedInstanceState);
Bundle bundle = getIntent().getExtras();
if(bundle != null){
mDeviceEntity = (WaterDeviceEntity) bundle.getSerializable("device_entity");
viewBinding.tvDeviceName.setText(mDeviceEntity.getDeviceName());
viewBinding.tvWifiName.setText(mDeviceEntity.getWifiName());
}
ImmersionBar.with(this)
.statusBarColor(R.color.white) // 设置状态栏颜色
.statusBarDarkFont(true) // 设置状态栏字体为黑色
.statusBarDarkFont(ThemeManager.isAppThemeLight(mContext)) // 白色状态栏图标
.navigationBarColor(R.color.mainBackgroundColor)
.titleBar(viewBinding.rlTitle)
.init();
viewBinding.includedTitle.tvTitle.setText(R.string.settings_title);
@@ -56,15 +70,21 @@ public class DeviceSettingsActivity extends BaseActivity<DeviceSettingsLayoutBin
public void onClick(View v){
switch (v.getId()){
case R.id.img_back:
Intent intent = new Intent();
intent.putExtra("device_entity",mDeviceEntity);
setResult(RESULT_OK,intent);
finish();
break;
case R.id.rl_dev_name:
showEditDialog(getString(R.string.device_setting_name),
getString(R.string.input_device_name_hint),
mDeviceEntity.getDeviceName(),
true,
getString(R.string.cancel_text),
getString(R.string.confirm_text), new OnDialogClick() {
getString(R.string.confirm_text),
BaseActivity.INPUT_TYPE_NORMAL,
new OnDialogClick() {
@Override
public void onCancelClick() {
}
@@ -76,6 +96,8 @@ public class DeviceSettingsActivity extends BaseActivity<DeviceSettingsLayoutBin
@Override
public void onConfirmClisk(String content) {
viewBinding.tvDeviceName.setText(content);
mDeviceEntity.setDeviceName(content);
mPresenter.updateDeviceInfo(mDeviceEntity);
}
@Override
@@ -85,13 +107,31 @@ public class DeviceSettingsActivity extends BaseActivity<DeviceSettingsLayoutBin
break;
case R.id.rl_dev_info:
goTo(mContext, DeviceInfoActivity.class,null);
Bundle bundleDev = new Bundle();
bundleDev.putSerializable("device_entity",mDeviceEntity);
goTo(mContext, DeviceInfoActivity.class,bundleDev);
break;
case R.id.rl_dev_wifi_manager:
Bundle bundle = new Bundle();
bundle.putInt(ConstantUtil.ACTIVITY_NAVIGATE_FLAG,200);
goToForResult(mContext, SelectWifiActivity.class,REQUEST_EVENT_CODE_10001,bundle);
showDialogtext(null, false, false, true,
getString(R.string.tip_text),
getString(R.string.reset_device_provision),
getString(R.string.cancel_text),
getString(R.string.confirm_text),
new BaseFragment.OnDialogClick() {
@Override
public void onCancelClick() {
}
@Override
public void onConfirmClick() {
Bundle bundle = new Bundle();
bundle.putInt(ConstantUtil.ACTIVITY_NAVIGATE_FLAG,100);
bundle.putSerializable("ble_device_entity",mDeviceEntity);
goToForResult(mContext, SelectWifiActivity.class,REQUEST_EVENT_CODE_10001,bundle);
}
});
break;
case R.id.rl_dev_unbind:
@@ -104,7 +144,7 @@ public class DeviceSettingsActivity extends BaseActivity<DeviceSettingsLayoutBin
@Override
public void onConfirmClick() {
ToastUtil.showShort(mContext,"确定");
mPresenter.unBindDevice(mDeviceEntity);
}
});
break;
@@ -112,6 +152,14 @@ public class DeviceSettingsActivity extends BaseActivity<DeviceSettingsLayoutBin
}
}
@Override
public void onBackPressed() {
Intent intent = new Intent();
intent.putExtra("device_entity",mDeviceEntity);
setResult(RESULT_OK,intent);
super.onBackPressed();
}
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
@@ -119,13 +167,46 @@ public class DeviceSettingsActivity extends BaseActivity<DeviceSettingsLayoutBin
if (resultCode == RESULT_OK) {
switch (requestCode) {
case REQUEST_EVENT_CODE_10001:
ToastUtil.showShort(mContext,data.getStringExtra("wifi_name"));
viewBinding.tvWifiName.setText(data.getStringExtra("wifi_name"));
mDeviceEntity.setWifiName(data.getStringExtra("wifi_name"));
mDeviceEntity.setWifiPassword(data.getStringExtra("wifi_psd"));
mPresenter.updateDeviceInfo(mDeviceEntity);
break;
}
}
}
}
/**
* 修改设备信息成功
* @param bean
*/
@Override
public void editDeviceInfoSuccess(BaseBean bean) {
hideDialogLoading();
}
@Override
public void finish() {
super.finish();
}
@Override
public void deleteDeviceSuccess(BaseBean bean) {
hideDialogLoading();
ToastUtil.showShort(mContext, getString(R.string.unbind_success));
EventBus.getDefault().post(new EventMessage(EventMessage.ACTIVITY_FINISH));
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
finish();
}
},500);
}
@Override
public int getLayoutResId(Bundle savedInstanceState) {
return 0;
@@ -142,22 +223,31 @@ public class DeviceSettingsActivity extends BaseActivity<DeviceSettingsLayoutBin
}
@Override
public void addDeviceSuccess(BaseBean bean) {
public void addDeviceSuccess(WaterDeviceEntity bean) {
}
@Override
public void editDeviceInfoSuccess(BaseBean bean) {
public void getDeviceDetailInfo(WaterDeviceEntity bean) {
}
@Override
public void turnOnOffDeviceSuccess(BaseBean bean, String status) {
}
@Override
public void deleteDeviceSuccess(BaseBean bean) {
public void queryDeviceBindStatusSuccess(WaterDeviceEntity bean) {
}
@Override
public void turnOnOffDeviceSuccess(BaseBean bean) {
public void queryDeviceWorkTimeSuccess(WaterDeviceEntity bean) {
}
}

View File

@@ -1,52 +1,88 @@
package com.ckkj.water.device;
import android.Manifest;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.net.wifi.ScanResult;
import android.net.wifi.WifiManager;
import android.os.Build;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.View;
import static android.view.View.GONE;
import static android.view.View.VISIBLE;
import androidx.core.app.ActivityCompat;
import androidx.recyclerview.widget.DividerItemDecoration;
import android.Manifest;
import android.content.Intent;
import android.graphics.drawable.AnimationDrawable;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.text.InputType;
import android.text.TextUtils;
import android.text.method.PasswordTransformationMethod;
import android.util.Log;
import android.view.View;
import android.widget.EditText;
import android.widget.ImageView;
import com.ckkj.water.ConstantUtil;
import com.ckkj.water.R;
import com.ckkj.water.base.BaseActivity;
import com.ckkj.water.databinding.DeviceResetWifiBinding;
import com.ckkj.water.device.adapter.WifiListAdapter;
import com.ckkj.water.device.mvp.DeviceContract;
import com.ckkj.water.device.mvp.DeviceImpl;
import com.ckkj.water.device.mvp.DevicePresenter;
import com.ckkj.water.espBle.EspProvisionManager;
import com.ckkj.water.espBle.ProvisionCallback;
import com.espressif.provisioning.WiFiAccessPoint;
import com.espressif.provisioning.listeners.WiFiScanListener;
import com.ckkj.water.index.entity.WaterDeviceEntity;
import com.ckkj.water.network.BaseBean;
import com.ckkj.water.permission.PermissionActivity;
import com.ckkj.water.utils.manager.ActivityManager;
import com.ckkj.water.utils.manager.ThemeManager;
import com.ckkj.water.utils.show.ToastUtil;
import com.ckkj.water.utils.text.TextUtil;
import com.gyf.immersionbar.ImmersionBar;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Set;
/**
* 配置wifi
*/
public class SelectWifiActivity extends BaseActivity<DeviceResetWifiBinding, DevicePresenter>
implements DeviceContract.DeviceView {
private WifiManager wifiManager;
private static final long BLE_CONNECT_TIMEOUT = 40 * 1000L;
//当前密码显示/隐藏
private boolean isPasswordVisible = false;
private WifiListAdapter wifiListAdapter;
private WifiScanReceiver wifiScanReceiver;
//100 来自设备添加, 200 来自设备信息
private int WITCH_FROM_CODE = 100;
private String mWifiName = "";
private WaterDeviceEntity mBleDeviceEntity;
private WaterDeviceEntity mRemoteDeviceEntity;
private EspProvisionManager espProvisionManager;
private boolean isBleConnecting = false;
private boolean isBleConnected = false;
private boolean keepBleConnectionForProvision = false;
private boolean isBleConnectTimedOut = false;
private boolean isBleConnectTimeoutRunning = false;
private Handler bleConnectHandler = new Handler(Looper.getMainLooper());
private AnimationDrawable animationDrawable;
private Handler handler = new Handler(Looper.getMainLooper());
private final Runnable bleConnectTask = new Runnable() {
@Override
public void run() {
connectBleDevice();
}
};
private final Runnable bleConnectTimeoutTask = new Runnable() {
@Override
public void run() {
handleBleConnectTimeout();
}
};
@Override
public DevicePresenter createPresenter() {
return new DevicePresenter(new DeviceImpl());
@@ -55,21 +91,17 @@ public class SelectWifiActivity extends BaseActivity<DeviceResetWifiBinding, Dev
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
wifiManager = (WifiManager) getApplicationContext().getSystemService(Context.WIFI_SERVICE);
wifiScanReceiver = new WifiScanReceiver();
ActivityManager.addActivity(this,getClass().getSimpleName() + "_" + ConstantUtil.ADD_DEVICE_FLAG);
}
@Override
protected void onResume() {
super.onResume();
registerReceiver(wifiScanReceiver, new IntentFilter(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION));
}
@Override
protected void onPause() {
super.onPause();
unregisterReceiver(wifiScanReceiver);
protected void onDestroy() {
super.onDestroy();
cancelBleConnectTask();
if (WITCH_FROM_CODE == 100 && espProvisionManager != null && !keepBleConnectionForProvision) {
espProvisionManager.disconnect();
espProvisionManager.setCallback(null);
}
}
@Override
@@ -78,10 +110,11 @@ public class SelectWifiActivity extends BaseActivity<DeviceResetWifiBinding, Dev
Bundle bundle = getIntent().getExtras();
if(bundle != null){
WITCH_FROM_CODE = bundle.getInt(ConstantUtil.ACTIVITY_NAVIGATE_FLAG);
mBleDeviceEntity = (WaterDeviceEntity) bundle.getSerializable("ble_device_entity");
}
ImmersionBar.with(this)
.statusBarColor(R.color.mainBackgroundColor)
.statusBarColor(R.color.color_gray_theme)
.statusBarDarkFont(ThemeManager.isAppThemeLight(mContext))
.titleBar(viewBinding.rlTitle)
.init();
@@ -92,10 +125,39 @@ public class SelectWifiActivity extends BaseActivity<DeviceResetWifiBinding, Dev
initListener();
initWifiList();
if (WITCH_FROM_CODE == 100) {
initEspProvision();
scheduleBleConnect();
}
}
private void startConnectAnimation() {
if (animationDrawable != null && animationDrawable.isRunning()) {
animationDrawable.stop();
}
viewBinding.ivConnectAnimation.setImageResource(R.drawable.anim_connect_ble_device);
animationDrawable = (AnimationDrawable) viewBinding.ivConnectAnimation.getDrawable();
if (animationDrawable != null) {
animationDrawable.start();
}
}
private void stopConnectAnimation() {
handler.removeCallbacksAndMessages(null);
if (animationDrawable != null) {
animationDrawable.stop();
animationDrawable = null;
}
viewBinding.linearConnectBle.setVisibility(GONE);
viewBinding.linearWifiContent.setVisibility(VISIBLE);
}
private void initWifiList() {
wifiListAdapter = new WifiListAdapter();
wifiListAdapter = new WifiListAdapter(mContext);
viewBinding.rvWifiList.setAdapter(wifiListAdapter);
wifiListAdapter.setOnWifiItemClickListener(wifiName -> {
mWifiName = wifiName;
@@ -110,6 +172,7 @@ public class SelectWifiActivity extends BaseActivity<DeviceResetWifiBinding, Dev
setClick(viewBinding.includedTitle.imgBack);
setClick(viewBinding.tvSelectWifi);
setClick(viewBinding.tvNext);
setClick(viewBinding.imgPsdShowHide);
}
private void setClick(View view) {
@@ -129,7 +192,7 @@ public class SelectWifiActivity extends BaseActivity<DeviceResetWifiBinding, Dev
boolean hasPermission = hasRecordPermission(permission);
if(!hasPermission){
goTo(mContext, PermissionActivity.class,null);
}else{
return;
}
scanWifi();
break;
@@ -143,36 +206,250 @@ public class SelectWifiActivity extends BaseActivity<DeviceResetWifiBinding, Dev
ToastUtil.showShort(mContext,getString(R.string.toast_select_wifi_psd_tip));
return;
}
String wifiPassword = viewBinding.etInputPsd.getText().toString();
if(WITCH_FROM_CODE == 100){
goTo(mContext,DeviceConnectActivity.class,null);
goToDeviceConnect(wifiPassword);
}else{
Intent intent = new Intent();
intent.putExtra("wifi_name",mWifiName);
intent.putExtra("wifi_psd",viewBinding.etInputPsd.getText().toString());
intent.putExtra("wifi_psd",wifiPassword);
setResult(RESULT_OK,intent);
finish();
}
break;
case R.id.img_psd_show_hide:
togglePasswordVisibility();
break;
}
}
private void togglePasswordVisibility() {
EditText etPassword = viewBinding.etInputPsd;
ImageView ivToggle = viewBinding.imgPsdShowHide;
if (etPassword == null || ivToggle == null) {
return;
}
if (isPasswordVisible) {
// 隐藏密码
etPassword.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD);
etPassword.setTransformationMethod(PasswordTransformationMethod.getInstance());
ivToggle.setImageResource(R.mipmap.icon_psd_hide);
} else {
// 显示密码
etPassword.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD);
etPassword.setTransformationMethod(null);
ivToggle.setImageResource(R.mipmap.icon_psd_show);
}
// 保持光标位置
etPassword.setSelection(etPassword.getText().length());
isPasswordVisible = !isPasswordVisible;
}
private void goToDeviceConnect(String wifiPassword) {
if (espProvisionManager == null) {
initEspProvision();
}
if (mBleDeviceEntity == null) {
ToastUtil.showShort(mContext, getString(R.string.device_not_initialized));
return;
}
isBleConnected = espProvisionManager != null && espProvisionManager.isConnected();
if (!isBleConnected) {
if (!isBleConnecting) {
scheduleBleConnect();
}
ToastUtil.showShort(mContext, getString(R.string.device_connecting_please_wait));
return;
}
Bundle bundle = new Bundle();
bundle.putString("wifi_name", mWifiName);
bundle.putString("wifi_password", wifiPassword);
bundle.putSerializable("ble_device_entity", mBleDeviceEntity);
keepBleConnectionForProvision = true;
cancelBleConnectTask();
goTo(mContext, DeviceConnectActivity.class, bundle);
finish();
}
private void initEspProvision() {
espProvisionManager = EspProvisionManager.init(mContext).setCallback(new ProvisionCallback() {
@Override
public void onConnecting() {
isBleConnecting = true;
isBleConnected = false;
startBleConnectTimeout();
Log.i("TEST","onConnecting");
}
@Override
public void onConnected() {
isBleConnecting = false;
isBleConnected = true;
cancelBleConnectTask();
Log.i("TEST","onConnected设备连接成功");
stopConnectAnimation();
ToastUtil.showShort(mContext, getString(R.string.device_connected_success));
//Tips 蓝牙扫描添加的设备不同于二维码扫描连接的设备由于无法拿到deviceNo所以需要请求接口获取
mPresenter.bindDeviceStatus(mBleDeviceEntity);
}
@Override
public void onProvisioning(int progress) {
Log.i("TEST","WIFI连接进度 == " + progress);
mProgressLoadingDialog.setProgress(progress);
}
@Override
public void onSuccess(String deviceName, String deviceType) {
Log.i("TEST","deviceName" + deviceName + "连接成功");
ToastUtil.showShort(mContext, getString(R.string.connection_success));
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
hideDialogLoading();
}
}, 800);
}
@Override
public void onFailed(int errorCode, String message) {
cancelBleConnectTask();
isBleConnecting = false;
if (errorCode != 0) {
isBleConnected = espProvisionManager != null && espProvisionManager .isConnected();
}
Log.i("TEST","errorCode == " + errorCode + " message == " + message);
ToastUtil.showShort(mContext, message);
stopConnectAnimation();
finish();
}
@Override
public void onDisconnected() {
isBleConnecting = false;
isBleConnected = false;
cancelBleConnectTask();
stopConnectAnimation();
Log.i("TEST","onDisconnected");
if (isBleConnectTimedOut) {
return;
}
ToastUtil.showShort(mContext, getString(R.string.device_disconnected));
}
@Override
public void onWifiListReceived(String[] wifiList) {
Log.i("TEST","onWifiListReceived-Msg==" + wifiList.toString());
}
@Override
public void onWifiListFailed(String message) {
Log.i("TEST","onWifiListFailed-Msg==" + message);
}
@Override
public void onProvisioningRejected() {
Log.i("TEST","onProvisioningRejected");
}
});
}
/**
* 连接设备
*/
private void scheduleBleConnect() {
startConnectAnimation();
startBleConnectTimeout();
bleConnectHandler.removeCallbacks(bleConnectTask);
bleConnectHandler.postDelayed(bleConnectTask, 1000);
}
private void connectBleDevice() {
if (WITCH_FROM_CODE != 100 || mBleDeviceEntity == null || espProvisionManager == null) {
return;
}
if (isBleConnected || isBleConnecting) {
return;
}
espProvisionManager.connect(mBleDeviceEntity.getMacAddress().toUpperCase(Locale.ROOT),
mBleDeviceEntity.getDeviceName());
}
private void startBleConnectTimeout() {
if (isBleConnected || keepBleConnectionForProvision) {
return;
}
if (isBleConnectTimeoutRunning) {
return;
}
isBleConnectTimedOut = false;
isBleConnectTimeoutRunning = true;
bleConnectHandler.removeCallbacks(bleConnectTimeoutTask);
bleConnectHandler.postDelayed(bleConnectTimeoutTask, BLE_CONNECT_TIMEOUT);
}
private void cancelBleConnectTask() {
isBleConnectTimeoutRunning = false;
bleConnectHandler.removeCallbacks(bleConnectTask);
bleConnectHandler.removeCallbacks(bleConnectTimeoutTask);
}
private void handleBleConnectTimeout() {
if (WITCH_FROM_CODE != 100 || isBleConnected || keepBleConnectionForProvision) {
return;
}
isBleConnectTimedOut = true;
isBleConnecting = false;
cancelBleConnectTask();
if (espProvisionManager != null) {
espProvisionManager.disconnect();
}
stopConnectAnimation();
ToastUtil.showShort(mContext, getString(R.string.ble_connect_timeout));
finish();
}
private void scanWifi() {
showLoadingDialog();
viewBinding.tvNext.setVisibility(View.GONE);
if (wifiManager != null && wifiManager.isWifiEnabled()) {
wifiManager.startScan();
} else {
ToastUtil.showShort(mContext, getString(R.string.wifi_not_enabled));
if (espProvisionManager == null || !espProvisionManager.isConnected()) {
ToastUtil.showShort(mContext, getString(R.string.device_not_connected_retry));
hideDialogLoading();
return;
}
espProvisionManager.scanWifiFromDevice(new WiFiScanListener() {
@Override
public void onWifiListReceived(ArrayList<WiFiAccessPoint> wifiList) {
runOnUiThread(() -> displayWifiListFromDevice(wifiList));
}
@Override
public void onWiFiScanFailed(Exception e) {
runOnUiThread(() -> {
ToastUtil.showShort(mContext, getString(R.string.scan_failed) + e.getMessage());
hideDialogLoading();
});
}
});
}
private void displayWifiList(List<ScanResult> scanResults) {
private void displayWifiListFromDevice(ArrayList<WiFiAccessPoint> wifiNetworks) {
Set<String> wifiSet = new HashSet<>();
List<String> wifiNameList = new ArrayList<>();
for (ScanResult result : scanResults) {
String wifiName = result.SSID;
for (WiFiAccessPoint network : wifiNetworks) {
String wifiName = network.getWifiName();
if (wifiName != null && !wifiName.isEmpty() && !wifiSet.contains(wifiName)) {
wifiSet.add(wifiName);
wifiNameList.add(wifiName);
@@ -191,8 +468,24 @@ public class SelectWifiActivity extends BaseActivity<DeviceResetWifiBinding, Dev
}
}
@Override
public void addDeviceSuccess(BaseBean bean) {
public void queryDeviceBindStatusSuccess(WaterDeviceEntity bean) {
mBleDeviceEntity = bean.getBindDevice();
}
@Override
public void queryDeviceWorkTimeSuccess(WaterDeviceEntity bean) {
}
@Override
public void addDeviceSuccess(WaterDeviceEntity bean) {
}
@Override
public void getDeviceDetailInfo(WaterDeviceEntity bean) {
}
@@ -207,34 +500,10 @@ public class SelectWifiActivity extends BaseActivity<DeviceResetWifiBinding, Dev
}
@Override
public void turnOnOffDeviceSuccess(BaseBean bean) {
public void turnOnOffDeviceSuccess(BaseBean bean, String status) {
}
private class WifiScanReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
if (WifiManager.SCAN_RESULTS_AVAILABLE_ACTION.equals(intent.getAction())) {
boolean success = intent.getBooleanExtra(WifiManager.EXTRA_RESULTS_UPDATED, false);
if (success) {
if (ActivityCompat.checkSelfPermission(mContext, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
// TODO: Consider calling
// ActivityCompat#requestPermissions
// here to request the missing permissions, and then overriding
// public void onRequestPermissionsResult(int requestCode, String[] permissions,
// int[] grantResults)
// to handle the case where the user grants the permission. See the documentation
// for ActivityCompat#requestPermissions for more details.
return;
}
List<ScanResult> results = wifiManager.getScanResults();
displayWifiList(results);
} else {
ToastUtil.showShort(mContext, getString(R.string.wifi_scan_failed));
}
}
}
}
@Override
public int getLayoutResId(Bundle savedInstanceState) {

View File

@@ -0,0 +1,31 @@
package com.ckkj.water.device.adapter;
import android.content.Context;
import android.text.TextUtils;
import androidx.annotation.Nullable;
import com.chad.library.adapter.base.BaseQuickAdapter;
import com.chad.library.adapter.base.BaseViewHolder;
import com.ckkj.water.R;
import com.ckkj.water.index.entity.WaterDeviceEntity;
import java.util.List;
/**
* @author fengxiaoyang
* @date 2026/6/3
* @description 扫描到的设备适配器
*/
public class BleScanDeviceAdapter extends BaseQuickAdapter<WaterDeviceEntity, BaseViewHolder> {
private Context mContext;
public BleScanDeviceAdapter(Context context,int layoutResId, @Nullable List<WaterDeviceEntity> data) {
super(layoutResId, data);
mContext = context;
}
@Override
protected void convert(BaseViewHolder helper, WaterDeviceEntity item) {
helper.setText(R.id.tv_device_name, TextUtils.isEmpty(item.getDeviceName())? "未知设备" : item.getDeviceName());
}
}

View File

@@ -17,7 +17,16 @@ public class DeviceTimeSelectAdapter extends BaseQuickAdapter<String, BaseViewHo
private List<String> mDatas = new ArrayList<>();
private int mSelPostion = -1;
public DeviceTimeSelectAdapter(Context context,int layoutResId, @Nullable List<String> data) {
public int getmSelPostion() {
return mSelPostion;
}
public void setmSelPostion(int mSelPostion) {
this.mSelPostion = mSelPostion;
}
public DeviceTimeSelectAdapter(Context context, int layoutResId, @Nullable List<String> data) {
super(layoutResId, data);
this.mContext = context;
this.mDatas = data;
@@ -32,7 +41,7 @@ public class DeviceTimeSelectAdapter extends BaseQuickAdapter<String, BaseViewHo
helper.setTextColor(R.id.tv_itme,mContext.getResources().getColor(R.color.white));
}else{
relTextBg.setBackground(mContext.getResources().getDrawable(R.drawable.shape_f7f7f7_line_button_bg));
helper.setTextColor(R.id.tv_itme,mContext.getResources().getColor(R.color.color_838080));
helper.setTextColor(R.id.tv_itme,mContext.getResources().getColor(R.color.textPrimaryColor));
}
}

View File

@@ -1,5 +1,6 @@
package com.ckkj.water.device;
package com.ckkj.water.device.adapter;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -10,6 +11,8 @@ import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.ckkj.water.R;
import com.ckkj.water.base.BaseActivity;
import com.ckkj.water.utils.manager.ThemeManager;
import java.util.ArrayList;
import java.util.List;
@@ -18,6 +21,10 @@ public class WifiListAdapter extends RecyclerView.Adapter<WifiListAdapter.WifiVi
private List<String> wifiList = new ArrayList<>();
private OnWifiItemClickListener listener;
private Context mContext;
public WifiListAdapter(BaseActivity mContext) {
this.mContext = mContext;
}
public interface OnWifiItemClickListener {
void onWifiItemClick(String wifiName);
@@ -49,6 +56,9 @@ public class WifiListAdapter extends RecyclerView.Adapter<WifiListAdapter.WifiVi
listener.onWifiItemClick(wifiName);
}
});
holder.ivWifiIcon.setImageResource(ThemeManager.isAppThemeLight(mContext) ?
R.mipmap.icon_wifi :
R.mipmap.icon_white_wifi );
}
@Override

View File

@@ -0,0 +1,18 @@
package com.ckkj.water.device.manage;
import android.content.Context;
import androidx.annotation.NonNull;
import no.nordicsemi.android.ble.BleManager;
/**
* @author fengxiaoyang
* @date 2026/5/30
* @description TODO: 描述该类的作用
*/
public class DeviceBleManager extends BleManager {
public DeviceBleManager(@NonNull Context context) {
super(context);
}
}

View File

@@ -1,6 +1,7 @@
package com.ckkj.water.device.mvp;
import com.ckkj.water.base.IView;
import com.ckkj.water.index.entity.WaterDeviceEntity;
import com.ckkj.water.index.mvp.IndexContract;
import com.ckkj.water.network.BaseBean;
@@ -24,17 +25,25 @@ public class DeviceContract {
void editDeviceInfo(JSONObject json, IndexContract.CallBack callBack);
//删除设备信息
void deleteDevice(JSONObject json, IndexContract.CallBack callBack);
void deleteDevice(String id, IndexContract.CallBack callBack);
//手动开启关闭设备
void turnOnOffDevice(JSONObject json, IndexContract.CallBack callBack);
//设备当前工作的开始时间和结束时间
void queryDeviceWorkTime(Map<String,String> map , IndexContract.CallBack callBack);
}
public interface DeviceView extends IView {
//添加设备成功g
void addDeviceSuccess(BaseBean bean);
void addDeviceSuccess(WaterDeviceEntity bean);
void getDeviceDetailInfo(WaterDeviceEntity bean);
void editDeviceInfoSuccess(BaseBean bean);
void deleteDeviceSuccess(BaseBean bean);
void turnOnOffDeviceSuccess(BaseBean bean);
void turnOnOffDeviceSuccess(BaseBean bean, String status);
void queryDeviceBindStatusSuccess(WaterDeviceEntity bean);
//查询设备目前工作状态
void queryDeviceWorkTimeSuccess(WaterDeviceEntity bean);
}
}

View File

@@ -1,11 +1,14 @@
package com.ckkj.water.device.mvp;
import com.ckkj.water.index.entity.WaterDeviceEntity;
import com.ckkj.water.index.mvp.IndexContract;
import com.ckkj.water.network.BaseBean;
import com.ckkj.water.network.NetWorkManager;
import com.ckkj.water.plan.entity.WaterPlanWeekEntity;
import org.json.JSONObject;
import java.util.List;
import java.util.Map;
import io.reactivex.Observer;
@@ -18,7 +21,32 @@ public class DeviceImpl implements DeviceContract.DataModel{
@Override
public void getDeviceInfomation(Map<String, String> map, IndexContract.CallBack callBack) {
String deviceID = map.get("deviceNo");
NetWorkManager.getRequest().getDeviceDetailInfo(NetWorkManager.getToken(), deviceID)
.subscribeOn(Schedulers.io())
.unsubscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<BaseBean<WaterDeviceEntity>>() {
@Override
public void onSubscribe(@NonNull Disposable d) {
}
@Override
public void onNext(@NonNull BaseBean<WaterDeviceEntity> bean) {
if (bean.getCode() == 200) {
callBack.success(bean.getData(),0);
}
}
@Override
public void onError(@NonNull Throwable e) {
callBack.fail(e.getMessage());
}
@Override
public void onComplete() {
}
});
}
/**
@@ -30,6 +58,46 @@ public class DeviceImpl implements DeviceContract.DataModel{
public void addDevice(JSONObject json, IndexContract.CallBack callBack) {
try {
NetWorkManager.getRequest().addDevice(NetWorkManager.getToken(), NetWorkManager.toRequestBody(json))
.subscribeOn(Schedulers.io())
.unsubscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<BaseBean<WaterDeviceEntity>>() {
@Override
public void onSubscribe(@NonNull Disposable d) {
}
@Override
public void onNext(@NonNull BaseBean<WaterDeviceEntity> bean) {
if (bean.getCode() == 200) {
callBack.success(bean.getData(),0);
} else {
callBack.fail(bean.getMessage());
}
}
@Override
public void onError(@NonNull Throwable e) {
callBack.fail(e.getMessage());
}
@Override
public void onComplete() {
}
});
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 修改设备信息
* @param json
* @param callBack
*/
@Override
public void editDeviceInfo(JSONObject json, IndexContract.CallBack callBack) {
try {
NetWorkManager.getRequest().updateDeviceInfo(NetWorkManager.getToken(), NetWorkManager.toRequestBody(json))
.subscribeOn(Schedulers.io())
.unsubscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
@@ -61,18 +129,116 @@ public class DeviceImpl implements DeviceContract.DataModel{
}
}
/**
* 删除设备
* @param callBack
*/
@Override
public void editDeviceInfo(JSONObject json, IndexContract.CallBack callBack) {
}
@Override
public void deleteDevice(JSONObject json, IndexContract.CallBack callBack) {
public void deleteDevice(String deviceNo, IndexContract.CallBack callBack) {
try {
NetWorkManager.getRequest().unBindDevice(NetWorkManager.getToken(), deviceNo)
.subscribeOn(Schedulers.io())
.unsubscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<BaseBean>() {
@Override
public void onSubscribe(@NonNull Disposable d) {
}
@Override
public void onNext(@NonNull BaseBean bean) {
if (bean.getCode() == 200) {
callBack.success(bean,0);
} else {
callBack.fail(bean.getMessage());
}
}
@Override
public void onError(@NonNull Throwable e) {
callBack.fail(e.getMessage());
}
@Override
public void onComplete() {
}
});
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 手动开启关闭设备
* @param json
* @param callBack
*/
@Override
public void turnOnOffDevice(JSONObject json, IndexContract.CallBack callBack) {
try {
NetWorkManager.getRequest().switchDevice(NetWorkManager.getToken(), NetWorkManager.toRequestBody(json))
.subscribeOn(Schedulers.io())
.unsubscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<BaseBean>() {
@Override
public void onSubscribe(@NonNull Disposable d) {
}
@Override
public void onNext(@NonNull BaseBean bean) {
if (bean.getCode() == 200) {
callBack.success(bean,0);
} else {
callBack.fail(bean.getMessage());
}
}
@Override
public void onError(@NonNull Throwable e) {
callBack.fail(e.getMessage());
}
@Override
public void onComplete() {
}
});
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 查询设备工作时间
* @param map
* @param callBack
*/
@Override
public void queryDeviceWorkTime(Map<String, String> map, IndexContract.CallBack callBack) {
NetWorkManager.getRequest().queryDeviceWorkTime(NetWorkManager.getToken(),map)
.subscribeOn(Schedulers.io())
.unsubscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<BaseBean<WaterDeviceEntity>>() {
@Override
public void onSubscribe(@NonNull Disposable d) {
}
@Override
public void onNext(@NonNull BaseBean<WaterDeviceEntity> bean) {
if (bean.getCode() == 200) {
callBack.success(bean.getData(),0);
}
}
@Override
public void onError(@NonNull Throwable e) {
callBack.fail(e.getMessage());
}
@Override
public void onComplete() {
}
});
}
}

View File

@@ -1,12 +1,17 @@
package com.ckkj.water.device.mvp;
import com.ckkj.water.base.BasePresenter;
import com.ckkj.water.index.entity.WaterDeviceEntity;
import com.ckkj.water.index.mvp.IndexContract;
import com.ckkj.water.index.mvp.IndexImpl;
import com.ckkj.water.index.mvp.IndexPresenter;
import com.ckkj.water.network.BaseBean;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
public class DevicePresenter extends BasePresenter<DeviceContract.DeviceView> {
@@ -16,20 +21,26 @@ public class DevicePresenter extends BasePresenter<DeviceContract.DeviceView> {
this.impl = impl;
}
public void addDevice() {
/**
* 添加设备
* @param mWifiName
* @param mWifiPassword
* @param mBleDeviceEntity
*/
public void addDevice(String deviceName,String mWifiName, String mWifiPassword, WaterDeviceEntity mBleDeviceEntity) {
try {
JSONObject json = new JSONObject();
json.put("deviceNo",System.currentTimeMillis() + "");
json.put("deviceName",new Random().nextInt(99) + "号设备");
json.put("wifiName","橙空科技WiFi");
json.put("wifiPassword","12321212");
json.put("deviceEm","213123123123");
json.put("deviceSn","sdfsd32423gdfgdf3");
json.put("fwVer","fwVer-56565644");
json.put("macAddress","2E:8H:00:KK:N7");
impl.addDevice(json, new IndexContract.CallBack<BaseBean>() {
json.put("deviceName",deviceName);
json.put("wifiName",mWifiName);
json.put("wifiPassword",mWifiPassword);
json.put("macAddress",mBleDeviceEntity.getMacAddress());
json.put("deviceNo", mBleDeviceEntity.getDeviceNo());
// json.put("deviceEm","213123123123");
// json.put("deviceSn","sdfsd32423gdfgdf3");
// json.put("fwVer","fwVer-56565644");
impl.addDevice(json, new IndexContract.CallBack<WaterDeviceEntity>() {
@Override
public void success(BaseBean bean,int total) {
public void success(WaterDeviceEntity bean,int total) {
if(DevicePresenter.this.getView() != null){
DevicePresenter.this.getView().addDeviceSuccess(bean);
}
@@ -37,11 +48,179 @@ public class DevicePresenter extends BasePresenter<DeviceContract.DeviceView> {
@Override
public void fail(String msg) {
if(DevicePresenter.this.getView() != null){
DevicePresenter.this.getView().showError( msg);
}
}
});
} catch (JSONException e) {
throw new RuntimeException(e);
}
}
/**
* 获取设备详情信息
* @param deviceNo
*/
public void getDeviceDetailInfo(String deviceNo) {
Map<String,String> map = new HashMap<>();
map.put("deviceNo",deviceNo);
impl.getDeviceInfomation(map, new IndexContract.CallBack<WaterDeviceEntity>() {
@Override
public void success(WaterDeviceEntity bean, int total) {
if(DevicePresenter.this.getView() != null){
DevicePresenter.this.getView().getDeviceDetailInfo(bean);
}
}
@Override
public void fail(String msg) {
if(DevicePresenter.this.getView() != null){
DevicePresenter.this.getView().showError( msg);
}
}
});
}
/**
* 修改设备信息
* @param mDeviceEntity
*/
public void updateDeviceInfo(WaterDeviceEntity mDeviceEntity) {
try {
JSONObject json = new JSONObject();
json.put("deviceNo",mDeviceEntity.getDeviceNo());
json.put("deviceName",mDeviceEntity.getDeviceName());
json.put("wifiName",mDeviceEntity.getWifiName());
json.put("wifiPassword",mDeviceEntity.getWifiPassword());
impl.editDeviceInfo(json, new IndexContract.CallBack<BaseBean>() {
@Override
public void success(BaseBean bean,int total) {
if(DevicePresenter.this.getView() != null){
DevicePresenter.this.getView().editDeviceInfoSuccess(bean);
}
}
@Override
public void fail(String msg) {
if(DevicePresenter.this.getView() != null){
DevicePresenter.this.getView().showError( msg);
}
}
});
} catch (JSONException e) {
throw new RuntimeException(e);
}
}
/**
* 解绑设备
* @param deviceEntity
*/
public void unBindDevice(WaterDeviceEntity deviceEntity) {
impl.deleteDevice(deviceEntity.getDeviceNo(), new IndexContract.CallBack<BaseBean>() {
@Override
public void success(BaseBean bean, int total) {
if (DevicePresenter.this.getView() != null) {
DevicePresenter.this.getView().deleteDeviceSuccess(bean);
}
}
@Override
public void fail(String msg) {
if (DevicePresenter.this.getView() != null) {
DevicePresenter.this.getView().showError(msg);
}
}
});
}
/**
* 开启/关闭浇水
* @param deviceEntity
* @param status
* @param duration
*/
public void switchDeviceWork(WaterDeviceEntity deviceEntity, String status, int duration) {
try {
JSONObject json = new JSONObject();
json.put("deviceNo",deviceEntity.getDeviceNo());
json.put("workStatus",status);
// json.put("startTime","09:50");
json.put("durationMin",duration + "");
impl.turnOnOffDevice(json, new IndexContract.CallBack<BaseBean>() {
@Override
public void success(BaseBean bean,int total) {
if(DevicePresenter.this.getView() != null){
DevicePresenter.this.getView().turnOnOffDeviceSuccess(bean,status);
}
}
@Override
public void fail(String msg) {
if(DevicePresenter.this.getView() != null){
DevicePresenter.this.getView().showError( msg);
}
}
});
} catch (JSONException e) {
throw new RuntimeException(e);
}
}
/**
* 绑定设备状态
* @param entity
*/
public void bindDeviceStatus(WaterDeviceEntity entity) {
try {
JSONObject json = new JSONObject();
json.put("macAddress",
entity.getMacAddress() == null ? "" : entity.getMacAddress().toLowerCase());
new IndexImpl().queryDeviceBindStatus(json, new IndexContract.CallBack<WaterDeviceEntity>() {
@Override
public void success(WaterDeviceEntity bean, int total) {
bean.setMacAddress(entity.getMacAddress());
bean.setDeviceName(entity.getDeviceName());
if(DevicePresenter.this.getView() != null){
DevicePresenter.this.getView().queryDeviceBindStatusSuccess(bean);
}
}
@Override
public void fail(String msg) {
if(DevicePresenter.this.getView() != null){
DevicePresenter.this.getView().showError(msg);
}
}
});
} catch (JSONException e) {
throw new RuntimeException(e);
}
}
/**
* 查询设备工作的开始时间和结束时间,计算进度
* @param deviceNo
*/
public void getDeviceWorkProgress(String deviceNo) {
Map<String,String> map = new HashMap<>();
map.put("deviceNo",deviceNo);
impl.queryDeviceWorkTime(map, new IndexContract.CallBack<WaterDeviceEntity>() {
@Override
public void success(WaterDeviceEntity bean, int total) {
if(DevicePresenter.this.getView() != null){
DevicePresenter.this.getView().queryDeviceWorkTimeSuccess(bean);
}
}
@Override
public void fail(String msg) {
if(DevicePresenter.this.getView() != null){
DevicePresenter.this.getView().showError( msg);
}
}
});
}
}

View File

@@ -19,6 +19,7 @@ import android.view.WindowManager;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.RelativeLayout;
import android.widget.TextView;
@@ -48,8 +49,10 @@ public class DialogAppUpdate {
public static View layoutView;
private Dialog mDialog;
private Activity mContext;
private TextView tvTitle,tvContent,tvConfirm,tvCancel;
private TextView tvTitle,tvContent,tvConfirm,tvCancel,tvVersionName;
private TextView tvProgressPercent;
private RelativeLayout rlUpdateContent;
private LinearLayout llProgressContainer,llButton;
private ImageView imgClose,imgClear;
private String startTime = "";
private String endTime = "";
@@ -84,7 +87,7 @@ public class DialogAppUpdate {
this.mContext = context;
this.mIsForceUpdate = isForceUpdate;
this.mVersionBean = bean;
mDwonLoadUrl = bean.getVersionUrl();
mDwonLoadUrl = bean.getDownloadUrl();
mDialog = new Dialog(context, R.style.ActionSheetDialogStyle);
//填充对话框的布局
layoutView = LayoutInflater.from(context).inflate(layoutId, null);
@@ -122,29 +125,28 @@ public class DialogAppUpdate {
dialogWindow.setAttributes(lp);
}
tvTitle = layoutView.findViewById(R.id.tv_title);
tvVersionName = layoutView.findViewById(R.id.tv_version);
tvContent = layoutView.findViewById(R.id.tv_update_content);
tvConfirm = layoutView.findViewById(R.id.tv_update);
tvCancel = layoutView.findViewById(R.id.tv_cencel);
tvCancel = layoutView.findViewById(R.id.tv_cancel);
progressBar = layoutView.findViewById(R.id.progress_bar);
rlUpdateContent = layoutView.findViewById(R.id.rel_file_content);
llProgressContainer = layoutView.findViewById(R.id.ll_progress_container);
llButton = layoutView.findViewById(R.id.Linear_button);
tvConfirm.setOnClickListener(onclick);
tvCancel.setOnClickListener(onclick);
if(isForceUpdate){
tvCancel.setVisibility(View.GONE);
}
// 初始化 DownloadManager
downloadManager = (DownloadManager) mContext.getSystemService(Context.DOWNLOAD_SERVICE);
notificationManager = (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
tvVersionName.setText(bean.getLatestVersion());
// 解析更新说明支持纯文本和HTML格式
String releaseNotes = bean.getReleaseNotes();
releaseNotes = releaseNotes.replace("\n", "<br>");
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
tvContent.setText(Html.fromHtml(bean.getVersionDescription(), Html.FROM_HTML_MODE_LEGACY));
tvContent.setText(Html.fromHtml(releaseNotes, Html.FROM_HTML_MODE_LEGACY));
} else {
tvContent.setText(Html.fromHtml(releaseNotes));
}
String [] desStr = bean.getVersionDescription().split("#");
String desLine = "";
for(String str : desStr){
desLine = desLine + str + "\n";
}
tvContent.setText(desLine);
tvContent.setLineSpacing(0, 1.2f);
}
@@ -163,9 +165,18 @@ public class DialogAppUpdate {
return;
}
}
if (!mIsForceUpdate && Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
if (ContextCompat.checkSelfPermission(mContext, Manifest.permission.POST_NOTIFICATIONS)
!= PackageManager.PERMISSION_GRANTED) {
if(mListener != null){
mListener.callBackGetPermisson(Manifest.permission.POST_NOTIFICATIONS);
}
return;
}
}
startUpdateApp();
break;
case R.id.tv_cencel:
case R.id.tv_cancel:
dismiss();
AppConfig.USER_CONFIRM_UPDATE_APP = true;
break;
@@ -176,8 +187,8 @@ public class DialogAppUpdate {
public void startUpdateApp() {
//强制更新不需要隐藏dialog
if(mIsForceUpdate){
progressBar.setVisibility(View.VISIBLE);
rlUpdateContent.setVisibility(View.GONE);
llProgressContainer.setVisibility(View.VISIBLE);
llButton.setVisibility(View.GONE);
progressBar.setMax(100);
}else{
ToastUtil.showShort(mContext,"可在任务栏查看下载进度");
@@ -188,7 +199,6 @@ public class DialogAppUpdate {
File apkFile = new File(downloadDir, fileName);
String apkPath = apkFile.getAbsolutePath();
DownLoadApk downloadTask = new DownLoadApk(mContext,mIsForceUpdate);
downloadTask.startDownload(mDwonLoadUrl, fileName,apkPath);
downloadTask.setDownLoadCallback(new DownLoadApk.DownLoadCallback() {
@Override
public void updateProgress(long currentProgress, long total) {
@@ -209,6 +219,7 @@ public class DialogAppUpdate {
}
}
});
downloadTask.startDownload(mDwonLoadUrl, fileName,apkPath);
}
public void show() {
@@ -224,4 +235,4 @@ public class DialogAppUpdate {
}
}
}

View File

@@ -0,0 +1,94 @@
package com.ckkj.water.dialog;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.annotation.SuppressLint;
import android.app.Dialog;
import android.content.Context;
import android.os.Bundle;
import android.os.Handler;
import android.view.WindowManager;
import android.view.animation.LinearInterpolator;
import android.widget.ImageView;
import android.widget.TextView;
import com.ckkj.water.R;
import com.timqi.sectorprogressview.ColorfulRingProgressView;
import java.util.Objects;
/**
* author:
* time: 2019/9/18 9:34
* desc:
* version: 1.0.0
*/
public class LoadingProgressDialog extends Dialog {
private Context context;
private int mProgress = 0;
private ColorfulRingProgressView mCircleLoading;
public LoadingProgressDialog(Context context) {
super(context); // 应用透明背景样式
this.context=context;
}
public LoadingProgressDialog(Context context, String s) {
super(context);
this.context=context;
}
public void setProgress(int progress) {
mProgress = progress;
if(mCircleLoading != null){
mCircleLoading.setPercent( progress);
}
}
public LoadingProgressDialog(Context context, int theme) {
super(context, theme);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
init();
}
@SuppressLint({"ResourceAsColor", "MissingInflatedId"})
private void init() {
// 设置对话框背景为透明
getWindow().setBackgroundDrawable(context.getResources().getDrawable(R.color.transparent));
getWindow().setDimAmount(0f);
setCancelable(true);
setCanceledOnTouchOutside(false);
setContentView(R.layout.dialog_progress_layout);//loading的xml文件
mCircleLoading = findViewById(R.id.circle_loading);
mCircleLoading.setStartAngle(0);
mCircleLoading.setPercent(mProgress);
//加载动画资源
WindowManager.LayoutParams params = Objects.requireNonNull(getWindow()).getAttributes();
params.width = WindowManager.LayoutParams.MATCH_PARENT;
params.height = WindowManager.LayoutParams.MATCH_PARENT;
getWindow().setAttributes(params);
// 可选: 设置窗口大小
getWindow().setLayout(WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.MATCH_PARENT);
}
@Override
public void show() {//开启
// if (context==null){
// return;
// }
super.show();
}
@Override
public void dismiss() {//关闭
// if (context==null){
// return;
// }
super.dismiss();
}
}

View File

@@ -0,0 +1,646 @@
package com.ckkj.water.espBle;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.content.Context;
import android.os.Handler;
import android.os.Looper;
import android.text.TextUtils;
import com.ckkj.water.AppConfig;
import com.espressif.provisioning.DeviceConnectionEvent;
import com.espressif.provisioning.ESPConstants;
import com.espressif.provisioning.ESPDevice;
import com.espressif.provisioning.WiFiAccessPoint;
import com.espressif.provisioning.listeners.ProvisionListener;
import com.espressif.provisioning.listeners.WiFiScanListener;
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.Set;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;
/**
* @author fengxiaoyang
* @date 2026/6/4
* @description 鎿嶄綔钃濈墮绠$悊绫?
*/
public class EspProvisionManager {
private static volatile EspProvisionManager instance;
private final Context context;
private final Handler mainHandler;
private final com.espressif.provisioning.ESPProvisionManager provisionManager;
private static final long CONNECT_COOLDOWN = 1200L;
private static final long QUICK_DISCONNECT_WINDOW = 3000L;
private static final long RETRY_DELAY = 1200L;
private static final long PROGRESS_UPDATE_INTERVAL = 500L;
private static final int MAX_CONNECT_RETRY = 2;
private static final int MAX_AUTO_PROGRESS = 99;
private ESPDevice espDevice;
private ProvisionCallback callback;
private boolean connecting;
private boolean connected;
private boolean provisioning;
private int provisionProgress;
private int provisionTargetProgress;
private boolean eventBusRegistered;
private boolean ignoreNextDisconnectEvent;
private boolean expectDisconnected; // 标记是否预期断开(配网成功后)
private String currentDeviceName;
private String currentDeviceType = ProvisionConfig.TRANSPORT_BLE;
private BluetoothDevice pendingBluetoothDevice;
private String pendingDeviceName;
private String pendingServiceUuid;
private String pendingProofOfPossession;
private String pendingUserName;
private int pendingSecurityType;
private int connectRetryCount;
private long lastDisconnectTime;
private long connectStartTime;
private final Runnable connectionTimeoutTask = new Runnable() {
@Override
public void run() {
if (connecting && !connected) {
connecting = false;
disconnectDeviceOnly();
lastDisconnectTime = System.currentTimeMillis();
if (retryConnectIfAllowed()) {
return;
}
resetState(true);
clearPendingConnect();
notifyFailed(ProvisionConfig.ERROR_CONNECT_TIMEOUT, "蓝牙连接超时");
disconnectDeviceOnly();
}
}
};
private final Runnable provisionTimeoutTask = new Runnable() {
@Override
public void run() {
if (provisioning) {
finishProvisionFailed(ProvisionConfig.ERROR_PROVISION_TIMEOUT, "配网超时");
}
}
};
private final Runnable connectRetryTask = new Runnable() {
@Override
public void run() {
startPendingConnect(false);
}
};
private final Runnable provisionProgressTask = new Runnable() {
@Override
public void run() {
if (!provisioning) {
return;
}
if (provisionProgress < provisionTargetProgress) {
notifyProvisioning(provisionProgress + 1);
}
if (provisionProgress < MAX_AUTO_PROGRESS) {
mainHandler.postDelayed(provisionProgressTask, PROGRESS_UPDATE_INTERVAL);
}
}
};
private EspProvisionManager(Context context) {
this.context = context.getApplicationContext();
this.mainHandler = new Handler(Looper.getMainLooper());
this.provisionManager = com.espressif.provisioning.ESPProvisionManager.getInstance(this.context);
ensureEventBusRegistered();
}
public static EspProvisionManager init(Context context) {
if (instance == null) {
synchronized (EspProvisionManager.class) {
if (instance == null) {
instance = new EspProvisionManager(context);
}
}
}
return instance;
}
public static EspProvisionManager get() {
if (instance == null) {
throw new RuntimeException("Please call init()");
}
return instance;
}
public EspProvisionManager setCallback(ProvisionCallback callback) {
this.callback = callback;
return this;
}
public ESPDevice getEspDevice() {
return espDevice;
}
public boolean isConnected() {
return connected;
}
public boolean isProvisioning() {
return provisioning;
}
public int getProvisionProgress() {
return provisionProgress;
}
public void connect(String deviceAddress, String deviceName) {
connect(deviceAddress, deviceName, AppConfig.BLUETOOTH_DEVICE_UUID);
}
public void connect(String deviceAddress, String deviceName, String serviceUuid) {
connect(deviceAddress, deviceName, serviceUuid, "", ProvisionConfig.DEFAULT_SECURITY);
}
public void connect(String deviceAddress, String deviceName, String serviceUuid,
String proofOfPossession, int securityType) {
BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
if (bluetoothAdapter == null || TextUtils.isEmpty(deviceAddress)) {
notifyFailed(ProvisionConfig.ERROR_INVALID_DEVICE, "蓝牙设备无效");
return;
}
try {
BluetoothDevice bluetoothDevice = bluetoothAdapter.getRemoteDevice(deviceAddress);
connect(bluetoothDevice, deviceName, serviceUuid, proofOfPossession, securityType);
} catch (IllegalArgumentException e) {
notifyFailed(ProvisionConfig.ERROR_INVALID_DEVICE, "蓝牙设备地址无效");
}
}
public void connect(BluetoothDevice bluetoothDevice, String serviceUuid) {
connect(bluetoothDevice, null, serviceUuid, "", ProvisionConfig.DEFAULT_SECURITY);
}
public void connect(BluetoothDevice bluetoothDevice, String deviceName, String serviceUuid,
String proofOfPossession, int securityType) {
connect(bluetoothDevice, deviceName, serviceUuid, proofOfPossession, "", securityType);
}
public void connect(BluetoothDevice bluetoothDevice, String deviceName, String serviceUuid,
String proofOfPossession, String userName, int securityType) {
if (bluetoothDevice == null) {
notifyFailed(ProvisionConfig.ERROR_INVALID_DEVICE, "蓝牙设备无效");
return;
}
if (connecting && pendingBluetoothDevice != null
&& TextUtils.equals(pendingBluetoothDevice.getAddress(), bluetoothDevice.getAddress())) {
return;
}
pendingBluetoothDevice = bluetoothDevice;
pendingDeviceName = deviceName;
pendingServiceUuid = TextUtils.isEmpty(serviceUuid) ? ProvisionConfig.SERVICE_UUID : serviceUuid;
pendingProofOfPossession = proofOfPossession == null ? "" : proofOfPossession;
pendingUserName = userName == null ? "" : userName;
pendingSecurityType = securityType;
connectRetryCount = 0;
startPendingConnect(true);
}
private void startPendingConnect(boolean respectCooldown) {
if (pendingBluetoothDevice == null) {
notifyFailed(ProvisionConfig.ERROR_INVALID_DEVICE, "蓝牙设备无效");
return;
}
if (provisioning) {
return;
}
mainHandler.removeCallbacks(connectRetryTask);
long elapsedSinceDisconnect = System.currentTimeMillis() - lastDisconnectTime;
if (respectCooldown && lastDisconnectTime > 0 && elapsedSinceDisconnect < CONNECT_COOLDOWN) {
mainHandler.postDelayed(connectRetryTask, CONNECT_COOLDOWN - elapsedSinceDisconnect);
return;
}
String displayName = !TextUtils.isEmpty(pendingDeviceName)
? pendingDeviceName : pendingBluetoothDevice.getName();
currentDeviceName = displayName;
currentDeviceType = ProvisionConfig.TRANSPORT_BLE;
boolean hadActiveDevice = espDevice != null && (connecting || connected || provisioning);
ignoreNextDisconnectEvent = hadActiveDevice;
disconnectDeviceOnly();
ensureEventBusRegistered();
espDevice = provisionManager.createESPDevice(
ESPConstants.TransportType.TRANSPORT_BLE,
parseSecurityType(pendingSecurityType)
);
espDevice.setBluetoothDevice(pendingBluetoothDevice);
espDevice.setPrimaryServiceUuid(pendingServiceUuid);
espDevice.setDeviceName(displayName);
espDevice.setProofOfPossession(pendingProofOfPossession);
espDevice.setUserName(pendingUserName);
connecting = true;
connected = false;
provisioning = false;
connectStartTime = System.currentTimeMillis();
mainHandler.removeCallbacks(connectionTimeoutTask);
mainHandler.postDelayed(connectionTimeoutTask, ProvisionConfig.CONNECTION_TIMEOUT);
notifyConnecting();
espDevice.connectBLEDevice(pendingBluetoothDevice, pendingServiceUuid);
}
private boolean retryConnectIfAllowed() {
if (pendingBluetoothDevice == null || provisioning || connected) {
return false;
}
if (connectRetryCount >= MAX_CONNECT_RETRY) {
return false;
}
connectRetryCount++;
resetState(true);
mainHandler.removeCallbacks(connectRetryTask);
mainHandler.postDelayed(connectRetryTask, RETRY_DELAY * connectRetryCount);
return true;
}
private void clearPendingConnect() {
pendingBluetoothDevice = null;
pendingDeviceName = null;
pendingServiceUuid = null;
pendingProofOfPossession = null;
pendingUserName = null;
pendingSecurityType = 0;
connectRetryCount = 0;
connectStartTime = 0;
}
public void provisionWifi(String ssid, String password) {
if (!checkConnected()) {
notifyFailed(ProvisionConfig.ERROR_NOT_CONNECTED, "设备未连接");
return;
}
if (TextUtils.isEmpty(ssid)) {
notifyFailed(ProvisionConfig.ERROR_WIFI_CONFIG_FAILED, "WiFi 名称不能为空");
return;
}
provisioning = true;
provisionProgress = 0;
provisionTargetProgress = 29;
mainHandler.removeCallbacks(provisionTimeoutTask);
mainHandler.postDelayed(provisionTimeoutTask, ProvisionConfig.PROVISION_TIMEOUT);
notifyProvisioning(0);
startProvisionProgressTask();
//wifi 密码 回调
espDevice.provision(ssid, password == null ? "" : password, new ProvisionListener() {
@Override
public void createSessionFailed(Exception e) {
finishProvisionFailed(ProvisionConfig.ERROR_SESSION_FAILED, getErrorMessage(e, "创建配网会话失败"));
}
@Override
public void wifiConfigSent() {
advanceProvisionProgress(30, 59);
}
@Override
public void wifiConfigFailed(Exception e) {
notifyProvisioningRejected();
finishProvisionFailed(ProvisionConfig.ERROR_WIFI_CONFIG_FAILED, getErrorMessage(e, "发送 WiFi 信息失败"));
}
@Override
public void wifiConfigApplied() {
advanceProvisionProgress(60, MAX_AUTO_PROGRESS);
}
@Override
public void wifiConfigApplyFailed(Exception e) {
finishProvisionFailed(ProvisionConfig.ERROR_WIFI_APPLY_FAILED, getErrorMessage(e, "应用 WiFi 信息失败"));
}
@Override
public void provisioningFailedFromDevice(ESPConstants.ProvisionFailureReason failureReason) {
finishProvisionFailed(ProvisionConfig.ERROR_PROVISION_FAILED, getProvisionFailureMessage(failureReason));
}
@Override
public void deviceProvisioningSuccess() {
finishProvisionSuccess();
}
@Override
public void onProvisioningFailed(Exception e) {
finishProvisionFailed(ProvisionConfig.ERROR_PROVISION_FAILED, getErrorMessage(e, "配网失败"));
}
});
}
/**
* 通过蓝牙请求 ESP32 扫描周围 WiFi
* @param scanListener 扫描结果监听器
*/
public void scanWifiFromDevice(WiFiScanListener scanListener) {
if (!checkConnected()) {
if (scanListener != null) {
scanListener.onWiFiScanFailed(new Exception("设备未连接"));
}
return;
}
if (espDevice == null) {
if (scanListener != null) {
scanListener.onWiFiScanFailed(new Exception("设备实例为空"));
}
return;
}
espDevice.scanNetworks(scanListener);
}
public void disconnect() {
boolean shouldNotify = connected || connecting || provisioning;
mainHandler.removeCallbacks(connectRetryTask);
disconnectDeviceOnly();
lastDisconnectTime = System.currentTimeMillis();
resetState(true);
clearPendingConnect();
if (shouldNotify) {
notifyDisconnected();
}
}
@Subscribe(threadMode = ThreadMode.MAIN)
public void onDeviceConnectionEvent(DeviceConnectionEvent event) {
if (event == null) {
return;
}
switch (event.getEventType()) {
case ESPConstants.EVENT_DEVICE_CONNECTED:
mainHandler.removeCallbacks(connectionTimeoutTask);
mainHandler.removeCallbacks(connectRetryTask);
connecting = false;
connected = true;
connectRetryCount = 0;
notifyConnected();
break;
case ESPConstants.EVENT_DEVICE_CONNECTION_FAILED:
mainHandler.removeCallbacks(connectionTimeoutTask);
mainHandler.removeCallbacks(provisionTimeoutTask);
boolean wasConnecting = connecting;
connecting = false;
connected = false;
provisioning = false;
lastDisconnectTime = System.currentTimeMillis();
if (wasConnecting && retryConnectIfAllowed()) {
break;
}
if (wasConnecting) {
resetState(true);
clearPendingConnect();
notifyFailed(ProvisionConfig.ERROR_CONNECT_FAILED, "蓝牙连接失败");
} else {
notifyFailed(ProvisionConfig.ERROR_PROVISION_FAILED, "设备通信失败");
}
break;
case ESPConstants.EVENT_DEVICE_DISCONNECTED:
if (ignoreNextDisconnectEvent) {
ignoreNextDisconnectEvent = false;
return;
}
mainHandler.removeCallbacks(connectionTimeoutTask);
mainHandler.removeCallbacks(provisionTimeoutTask);
boolean shouldNotify = connected || connecting || provisioning;
boolean expectedDisconnect = expectDisconnected;
boolean wasConnecting2 = connecting;
long connectDuration = System.currentTimeMillis() - connectStartTime;
lastDisconnectTime = System.currentTimeMillis();
resetState(true);
if (wasConnecting2 && !expectedDisconnect
&& connectDuration < QUICK_DISCONNECT_WINDOW
&& retryConnectIfAllowed()) {
break;
}
if (wasConnecting2 && !expectedDisconnect) {
clearPendingConnect();
notifyFailed(ProvisionConfig.ERROR_CONNECT_FAILED, "蓝牙连接失败");
break;
}
if (shouldNotify) {
// 如果是配网成功后的预期断开,不发送断开回调
// 因为 onSuccess 已经通知过了
if (!expectedDisconnect) {
notifyDisconnected();
}
}
break;
default:
break;
}
}
private boolean checkConnected() {
return espDevice != null && connected;
}
private void ensureEventBusRegistered() {
if (!eventBusRegistered) {
EventBus.getDefault().register(this);
eventBusRegistered = true;
}
}
private void disconnectDeviceOnly() {
if (espDevice != null) {
try {
espDevice.disconnectDevice();
} catch (Exception ignored) {
}
}
}
private void resetState(boolean clearDevice) {
mainHandler.removeCallbacks(connectionTimeoutTask);
mainHandler.removeCallbacks(provisionTimeoutTask);
stopProvisionProgressTask();
connecting = false;
connected = false;
provisioning = false;
provisionProgress = 0;
provisionTargetProgress = 0;
ignoreNextDisconnectEvent = false;
expectDisconnected = false;
if (clearDevice) {
espDevice = null;
}
}
private ESPConstants.SecurityType parseSecurityType(int securityType) {
if (securityType == ProvisionConfig.SECURITY_0) {
return ESPConstants.SecurityType.SECURITY_0;
} else if (securityType == ProvisionConfig.SECURITY_1) {
return ESPConstants.SecurityType.SECURITY_1;
} else {
return ESPConstants.SecurityType.SECURITY_2;
}
}
private void finishProvisionSuccess() {
mainHandler.removeCallbacks(provisionTimeoutTask);
stopProvisionProgressTask();
provisioning = false;
expectDisconnected = true; // 标记为预期断开
notifyProvisioning(100);
notifySuccess();
}
private void finishProvisionFailed(int errorCode, String message) {
mainHandler.removeCallbacks(provisionTimeoutTask);
stopProvisionProgressTask();
provisioning = false;
notifyFailed(errorCode, message);
}
private void advanceProvisionProgress(int minProgress, int targetProgress) {
int nextProgress = Math.max(provisionProgress, minProgress);
provisionTargetProgress = Math.max(nextProgress, Math.min(targetProgress, MAX_AUTO_PROGRESS));
notifyProvisioning(nextProgress);
startProvisionProgressTask();
}
private void startProvisionProgressTask() {
mainHandler.removeCallbacks(provisionProgressTask);
mainHandler.postDelayed(provisionProgressTask, PROGRESS_UPDATE_INTERVAL);
}
private void stopProvisionProgressTask() {
mainHandler.removeCallbacks(provisionProgressTask);
}
private String getProvisionFailureMessage(ESPConstants.ProvisionFailureReason failureReason) {
if (failureReason == ESPConstants.ProvisionFailureReason.AUTH_FAILED) {
return "WiFi 密码错误";
} else if (failureReason == ESPConstants.ProvisionFailureReason.NETWORK_NOT_FOUND) {
return "未找到指定 WiFi";
} else if (failureReason == ESPConstants.ProvisionFailureReason.DEVICE_DISCONNECTED) {
return "设备已断开连接";
} else {
return "设备配网失败";
}
}
private String getErrorMessage(Exception e, String defaultMessage) {
if (e != null && !TextUtils.isEmpty(e.getMessage())) {
return e.getMessage();
}
return defaultMessage;
}
private void runOnMainThread(Runnable runnable) {
if (Looper.myLooper() == Looper.getMainLooper()) {
runnable.run();
} else {
mainHandler.post(runnable);
}
}
private void notifyConnecting() {
runOnMainThread(new Runnable() {
@Override
public void run() {
if (callback != null) {
callback.onConnecting();
}
}
});
}
private void notifyConnected() {
runOnMainThread(new Runnable() {
@Override
public void run() {
if (callback != null) {
callback.onConnected();
}
}
});
}
private void notifyProvisioning(final int progress) {
provisionProgress = Math.max(0, Math.min(progress, 100));
runOnMainThread(new Runnable() {
@Override
public void run() {
provisionProgress = Math.max(0, Math.min(progress, 100));
if (callback != null) {
callback.onProvisioning(provisionProgress);
}
}
});
}
private void notifySuccess() {
runOnMainThread(new Runnable() {
@Override
public void run() {
if (callback != null) {
callback.onSuccess(currentDeviceName, currentDeviceType);
}
}
});
}
private void notifyFailed(final int errorCode, final String message) {
runOnMainThread(new Runnable() {
@Override
public void run() {
if (callback != null) {
callback.onFailed(errorCode, message);
}
}
});
}
private void notifyDisconnected() {
runOnMainThread(new Runnable() {
@Override
public void run() {
if (callback != null) {
callback.onDisconnected();
}
}
});
}
private void notifyProvisioningRejected() {
runOnMainThread(new Runnable() {
@Override
public void run() {
if (callback != null) {
callback.onProvisioningRejected();
}
}
});
}
}

View File

@@ -0,0 +1,61 @@
package com.ckkj.water.espBle;
/**
* @author fengxiaoyang
* @date 2026/6/4
* @description 蓝牙设备配网回调接口
*/
public interface ProvisionCallback {
/**
* 正在连接设备
*/
void onConnecting();
/**
* 设备连接成功
*/
void onConnected();
/**
* 正在配网中
* @param progress 配网进度 (0-100)
*/
void onProvisioning(int progress);
/**
* 配网成功
* @param deviceName 设备名称
* @param deviceType 设备类型
*/
void onSuccess(String deviceName, String deviceType);
/**
* 配网失败
* @param errorCode 错误码
* @param message 错误信息
*/
void onFailed(int errorCode, String message);
/**
* 设备断开连接
*/
void onDisconnected();
/**
* WiFi列表获取成功
* @param wifiList WiFi列表
*/
void onWifiListReceived(String[] wifiList);
/**
* 获取WiFi列表失败
* @param message 错误信息
*/
void onWifiListFailed(String message);
/**
* 配网被拒绝(设备端拒绝配网请求)
*/
void onProvisioningRejected();
}

View File

@@ -0,0 +1,135 @@
package com.ckkj.water.espBle;
import android.os.Build;
import com.espressif.provisioning.ESPConstants;
/**
* @author fengxiaoyang
* @date 2026/6/4
* @description 蓝牙配网配置管理类
*/
public class ProvisionConfig {
/**
* ESP BLE Service UUID
*/
public static final String SERVICE_UUID =
"0000ffff-0000-1000-8000-00805f9b34fb";
/**
* ESP BLE Characteristic UUID for writes
*/
public static final String CHARACTERISTIC_UUID =
"0000ff01-0000-1000-8000-00805f9b34fb";
/**
* ESP BLE Characteristic UUID for notifications
*/
public static final String NOTIFY_UUID =
"0000ff02-0000-1000-8000-00805f9b34fb";
/**
* 设备传输的协议类型
*/
public static final String TRANSPORT_BLE = "ble";
/**
* 设备前缀 (用于过滤设备)
*/
public static final String DEVICE_PREFIX = "PROV_";
/**
* 安全类型 - SECURITY_0 (无安全)
*/
public static final int SECURITY_0 = ESPConstants.SecurityType.SECURITY_0.ordinal();
/**
* 安全类型 - SECURITY_1 (推荐)
*/
public static final int SECURITY_1 = ESPConstants.SecurityType.SECURITY_1.ordinal();
/**
* 默认安全类型
*/
public static final int DEFAULT_SECURITY = SECURITY_1;
/**
* 默认 PoP需和 ESP 固件保持一致
*/
public static final String DEFAULT_PROOF_OF_POSSESSION = "abcd1234";
/**
* Security2 使用的默认用户名
*/
public static final String DEFAULT_USER_NAME = "";
/**
* 连接超时时间 (毫秒)
*/
public static final int CONNECTION_TIMEOUT = 30000;
/**
* 配网超时时间 (毫秒)
*/
public static final int PROVISION_TIMEOUT = 120000;
public static final int ERROR_NOT_INITIALIZED = 1000;
public static final int ERROR_INVALID_DEVICE = 1001;
public static final int ERROR_CONNECT_TIMEOUT = 1002;
public static final int ERROR_CONNECT_FAILED = 1003;
public static final int ERROR_NOT_CONNECTED = 1004;
public static final int ERROR_SESSION_FAILED = 1005;
public static final int ERROR_WIFI_CONFIG_FAILED = 1006;
public static final int ERROR_WIFI_APPLY_FAILED = 1007;
public static final int ERROR_PROVISION_FAILED = 1008;
public static final int ERROR_PROVISION_TIMEOUT = 1009;
public static final int ERROR_WIFI_SCAN_FAILED = 1010;
/**
* 配网版本 (可根据实际固件调整)
*/
public static final String VERSION = "v1.1";
/**
* 生成蓝牙扫描过滤器
* @return 服务UUID数组
*/
public static String[] getScanServiceUuids() {
return new String[]{SERVICE_UUID};
}
/**
* 生成设备前缀过滤器 (用于过滤非ESP设备)
* @return 设备前缀
*/
public static String getDevicePrefix() {
return DEVICE_PREFIX;
}
/**
* 获取当前Android版本号
* @return Android版本号
*/
public static int getAndroidVersion() {
return Build.VERSION.SDK_INT;
}
/**
* 检查是否为Android 10及以上版本
* @return true 表示支持
*/
public static boolean isAndroid10OrAbove() {
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q;
}
}

View File

@@ -25,6 +25,7 @@ import com.ckkj.water.ConstantUtil;
import com.ckkj.water.R;
import com.ckkj.water.base.BaseActivity;
import com.ckkj.water.databinding.GuideActivityLayoutBinding;
import com.ckkj.water.login.LoginActivity;
import com.ckkj.water.login.entity.LoginEntity;
import com.ckkj.water.login.mvp.LoginContract;
import com.ckkj.water.login.mvp.LoginImpl;
@@ -42,9 +43,6 @@ public class GuideActivity extends BaseActivity<GuideActivityLayoutBinding, Logi
private List<Drawable> mImgUrls = new ArrayList<>();
private List<ImageView> mPointList = new ArrayList<>();
private boolean mHasEnterAppFlag = false;
private String desc[] = {"探索你的个性特征",
"一键生成,智能排盘工具",
"贴心提供每日生活指南"};
private int[] guideDrawableIds = {
R.mipmap.img_guide_1,
@@ -98,8 +96,11 @@ public class GuideActivity extends BaseActivity<GuideActivityLayoutBinding, Logi
viewBinding.tvStart.setOnClickListener(v -> {
SharePreUtil.putBoolean(ConstantUtil.SHARE_PRE_NAME, mContext, ConstantUtil.FIRST_ENTER_APP_FLAG, true);
Intent intent = new Intent(mContext, MainActivity.class);
startActivity(intent);
if(AppConfig.USER_LOGIN){
goTo(mContext, MainActivity.class,null);
}else{
goTo(mContext, LoginActivity.class,null);
}
finish();
});
}
@@ -135,6 +136,11 @@ public class GuideActivity extends BaseActivity<GuideActivityLayoutBinding, Logi
public void loginBySmsCodeSuccess(LoginEntity entity) {
}
@Override
public void updateUserPasswordSuccess(BaseBean bean) {
}
class MyAdapter extends PagerAdapter {
@Override
public int getCount() {

View File

@@ -1,20 +1,20 @@
package com.ckkj.water.guide;
import android.content.Intent;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.os.Bundle;
import android.os.Handler;
import android.view.View;
import com.ckkj.water.AppConfig;
import com.ckkj.water.login.LoginActivity;
import com.ckkj.water.login.RegisterActivity;
import com.ckkj.water.login.RegisterSuccessActivity;
import com.gyf.immersionbar.ImmersionBar;
import com.ckkj.water.ConstantUtil;
import com.ckkj.water.MyApplication;
import com.ckkj.water.R;
import com.ckkj.water.base.BaseActivity;
import com.ckkj.water.base.entity.MineUserInfoBean;
import com.ckkj.water.mine.entity.MineUserInfoBean;
import com.ckkj.water.databinding.GuideLayoutBinding;
import com.ckkj.water.main.MainContract;
import com.ckkj.water.main.MainImpl;
@@ -26,8 +26,9 @@ import com.ckkj.water.network.BaseBean;
import com.ckkj.water.utils.dataUtil.SharePreUtil;
import com.ckkj.water.utils.manager.ActivityManager;
import java.util.Locale;
import me.jessyan.autosize.internal.CancelAdapt;
import me.jessyan.autosize.internal.CustomAdapt;
/**
* @author fengxiaoyang
@@ -56,8 +57,13 @@ public class LaunchActivity extends BaseActivity<GuideLayoutBinding, MainPresent
//首次进入,弹框提示隐私政策
if (mIsFirstEnterApp) {
//首次进入
showDialogtext("温馨提示", mContext.getResources().getString(R.string.tips_yinsizhengce_dialog),
"同意", "拒绝", "用户隐私协议", new OnDialogClick() {
showDialogtext(
getSystemLanguageString(R.string.tip_text),
getSystemLanguageString(R.string.tips_yinsizhengce_dialog),
getSystemLanguageString(R.string.agree),
getSystemLanguageString(R.string.reject),
getSystemLanguageString(R.string.user_agreement)
, new OnDialogClick() {
@Override
public void onCancelClick() {
@@ -116,6 +122,16 @@ public class LaunchActivity extends BaseActivity<GuideLayoutBinding, MainPresent
finish();
}
private String getSystemLanguageString(int resId) {
Locale systemLocale = Resources.getSystem().getConfiguration().getLocales().get(0);
Locale targetLocale = Locale.CHINESE.getLanguage().equals(systemLocale.getLanguage())
? Locale.SIMPLIFIED_CHINESE
: Locale.ENGLISH;
Configuration configuration = new Configuration(getResources().getConfiguration());
configuration.setLocale(targetLocale);
return createConfigurationContext(configuration).getString(resId);
}
@Override
public MainPresenter createPresenter() {

View File

@@ -10,12 +10,12 @@ import androidx.fragment.app.Fragment;
import com.ckkj.water.R;
import com.ckkj.water.base.BaseFragment;
import com.ckkj.water.databinding.HistoryFragmentLayoutBinding;
import com.ckkj.water.history.entity.WaterStatisticsEntity;
import com.ckkj.water.history.entity.WateringRecord;
import com.ckkj.water.history.mvp.HistoryContract;
import com.ckkj.water.history.mvp.HistoryPresenter;
import com.ckkj.water.network.BaseBean;
import com.ckkj.water.plan.BindDeviceFragment;
import com.ckkj.water.plan.WaterConfigFragment;
import com.ckkj.water.plate.adapter.ViewPagerAdapter;
import com.ckkj.water.plan.adapter.ViewPagerAdapter;
import com.ckkj.water.utils.manager.ThemeManager;
import com.gyf.immersionbar.ImmersionBar;
@@ -97,4 +97,19 @@ public class HistoryFragment extends BaseFragment<HistoryFragmentLayoutBinding,
public void logOut(BaseBean bean) {
}
@Override
public void getHistoryListSuccess(List<WateringRecord> msg, int total) {
}
@Override
public void deleteHistorySuccess(BaseBean msg, int position) {
}
@Override
public void getHistoryStatisticsSuccess(WaterStatisticsEntity entity) {
}
}

View File

@@ -4,25 +4,129 @@ import android.os.Bundle;
import com.ckkj.water.base.BaseFragment;
import com.ckkj.water.databinding.WaterCountFragmentLayoutBinding;
import com.ckkj.water.history.entity.WaterStatisticsEntity;
import com.ckkj.water.history.entity.WateringRecord;
import com.ckkj.water.history.mvp.HistoryContract;
import com.ckkj.water.history.mvp.HistoryImpl;
import com.ckkj.water.history.mvp.HistoryPresenter;
import com.ckkj.water.index.entity.WaterDeviceEntity;
import com.ckkj.water.network.BaseBean;
import com.ckkj.water.plan.entity.WaterPlanWeekEntity;
import com.ckkj.water.plan.mvp.WaterPlanContract;
import com.ckkj.water.plan.mvp.WaterPlanImpl;
import com.ckkj.water.plan.mvp.WaterPlanPresenter;
import com.ckkj.water.utils.show.ToastUtil;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Locale;
/**
* @author fengxiaoyang
* @date 2026/5/16
* @description TODO: 描述该类的作用
* @description TODO: 统计界面
*/
public class StatisticFragment extends BaseFragment<WaterCountFragmentLayoutBinding, WaterPlanPresenter>
implements WaterPlanContract.WaterPlanView {
public class StatisticFragment extends BaseFragment<WaterCountFragmentLayoutBinding, HistoryPresenter>
implements HistoryContract.HistoryView {
@Override
protected void onResumeInitData() {
super.onResumeInitData();
showLoadingDialog();
mPresenter.getWaterStatistic();
}
@Override
public void initData(Bundle state) {
}
@Override
public WaterPlanPresenter createPresenter() {
return null;
public void getHistoryStatisticsSuccess(WaterStatisticsEntity entity) {
hideDialogLoading();
viewBinding.tvTotalValue.setText(entity.getCount()+"");
viewBinding.tvThisWeekValue.setText(entity.getWeekCount()+"");
viewBinding.tvThisMonthValue.setText(entity.getMonCount()+"");
viewBinding.tvPlanValue.setText(entity.getSchedule()+"");
viewBinding.tvManuallyValue.setText(entity.getManualNum()+"");
setTotalDuration(entity.getAllTime());
setAverageDuration(entity.getAverageTime());
setWeekAndMonthDate();
// viewBinding.tvTotalValue.setText(entity.getCount()+"");
}
private void setTotalDuration(int totalMinutes) {
if (totalMinutes < 60) {
viewBinding.tvTotalDurationValue.setText(totalMinutes + "");
viewBinding.tvTotalDurationHourUnit.setText("min");
viewBinding.tvTotalDurationMinValue.setVisibility(android.view.View.GONE);
viewBinding.tvTotalDurationMinUnit.setVisibility(android.view.View.GONE);
} else {
int hours = totalMinutes / 60;
int minutes = totalMinutes % 60;
viewBinding.tvTotalDurationHourUnit.setText("h");
viewBinding.tvTotalDurationValue.setText(hours + "");
if (minutes == 0) {
viewBinding.tvTotalDurationMinValue.setVisibility(android.view.View.GONE);
viewBinding.tvTotalDurationMinUnit.setVisibility(android.view.View.GONE);
} else {
viewBinding.tvTotalDurationMinValue.setVisibility(android.view.View.VISIBLE);
viewBinding.tvTotalDurationMinUnit.setVisibility(android.view.View.VISIBLE);
viewBinding.tvTotalDurationMinValue.setText(minutes + "");
}
}
}
private void setAverageDuration(int avgMinutes) {
if (avgMinutes < 60) {
viewBinding.tvAverageHourValue.setText(avgMinutes + "");
viewBinding.tvAverageHourUnit.setText("min");
viewBinding.tvAverageMinValue.setVisibility(android.view.View.GONE);
viewBinding.tvAverageMinUnit.setVisibility(android.view.View.GONE);
} else {
int hours = avgMinutes / 60;
int minutes = avgMinutes % 60;
viewBinding.tvAverageHourUnit.setText("h");
viewBinding.tvAverageHourValue.setText(hours + "");
if (minutes == 0) {
viewBinding.tvAverageMinValue.setVisibility(android.view.View.GONE);
viewBinding.tvAverageMinUnit.setVisibility(android.view.View.GONE);
} else {
viewBinding.tvAverageMinValue.setVisibility(android.view.View.VISIBLE);
viewBinding.tvAverageMinUnit.setVisibility(android.view.View.VISIBLE);
viewBinding.tvAverageMinValue.setText(minutes + "");
}
}
}
private void setWeekAndMonthDate() {
SimpleDateFormat monthFormat = new SimpleDateFormat("M月", Locale.CHINA);
SimpleDateFormat dayFormat = new SimpleDateFormat("M.d", Locale.CHINA);
Calendar calendar = Calendar.getInstance();
// 设置当月日期显示
viewBinding.tvThisMonthDate.setVisibility(android.view.View.VISIBLE);
viewBinding.tvThisMonthDate.setText(monthFormat.format(calendar.getTime()));
// 计算本周的开始日期(周一)和结束日期(周日)
int dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK);
int mondayOffset = (dayOfWeek == Calendar.SUNDAY) ? -6 : Calendar.MONDAY - dayOfWeek;
calendar.add(Calendar.DAY_OF_MONTH, mondayOffset);
Date weekStart = calendar.getTime();
calendar.add(Calendar.DAY_OF_MONTH, 6);
Date weekEnd = calendar.getTime();
// 设置本周日期显示
viewBinding.tvWeekDate.setVisibility(android.view.View.VISIBLE);
viewBinding.tvWeekDate.setText(dayFormat.format(weekStart) + " - " + dayFormat.format(weekEnd));
}
@Override
public HistoryPresenter createPresenter() {
return new HistoryPresenter(new HistoryImpl());
}
@Override
@@ -32,11 +136,24 @@ public class StatisticFragment extends BaseFragment<WaterCountFragmentLayoutBind
@Override
public void showError(String message) {
hideDialogLoading();
ToastUtil.showShort(mContext,message);
}
@Override
public void logOut(BaseBean bean) {
}
@Override
public void getHistoryListSuccess(List<WateringRecord> msg, int total) {
}
@Override
public void deleteHistorySuccess(BaseBean msg, int position) {
}
}

View File

@@ -8,19 +8,25 @@ import com.ckkj.water.R;
import com.ckkj.water.base.BaseFragment;
import com.ckkj.water.custom.CustomTimeFilterPopupView;
import com.ckkj.water.custom.CustomTypeFilterPopupView;
import com.ckkj.water.custom.view.CustomRefreshHeader;
import com.ckkj.water.databinding.TabHistoryFragmentLayoutBinding;
import com.ckkj.water.history.adapter.WateringHistoryAdapter;
import com.ckkj.water.history.entity.WaterStatisticsEntity;
import com.ckkj.water.history.entity.WateringRecord;
import com.ckkj.water.history.mvp.HistoryContract;
import com.ckkj.water.history.mvp.HistoryImpl;
import com.ckkj.water.history.mvp.HistoryPresenter;
import com.ckkj.water.network.BaseBean;
import com.ckkj.water.plan.entity.WaterPlanWeekEntity;
import com.ckkj.water.utils.manager.ThemeManager;
import com.ckkj.water.utils.show.ToastUtil;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.lxj.xpopup.XPopup;
import com.lxj.xpopup.core.BasePopupView;
import com.lxj.xpopup.interfaces.SimpleCallback;
import com.scwang.smart.refresh.footer.ClassicsFooter;
import com.scwang.smart.refresh.layout.api.RefreshHeader;
import java.lang.reflect.Type;
import java.util.ArrayList;
@@ -34,28 +40,70 @@ import java.util.List;
public class TabHistoryFragment extends BaseFragment<TabHistoryFragmentLayoutBinding, HistoryPresenter>
implements HistoryContract.HistoryView {
List<WateringRecord> recordList = new ArrayList<>();
private List<WateringRecord> recordList = new ArrayList<>();
private WateringHistoryAdapter mAdapter;
private int mCurrentPage = 1;
private String mFilterStartTime = "";
private String mFilterEndTime = "";
private int mFilterType = -1; //0-排程 1-手动
@Override
protected void onResumeInitData() {
super.onResumeInitData();
showLoadingDialog();
getWaterHistoryList();
}
@Override
public void initData(Bundle state) {
String jsonContent = getString(R.string.watering_device_list_json);
Type type = new TypeToken<List<WateringRecord>>() {}.getType();
recordList = new Gson().fromJson(jsonContent, type);
mAdapter = new WateringHistoryAdapter(mContext,R.layout.tab_history_item_layout,recordList);
viewBinding.rvHisttory.setAdapter(mAdapter);
initListener();
RefreshHeader header = new CustomRefreshHeader(mContext);
viewBinding.refresh.setRefreshHeader(header);
viewBinding.refresh.setRefreshFooter(new ClassicsFooter(mContext));
viewBinding.refresh.setOnRefreshListener(layout -> {
mCurrentPage = 1;
mFilterStartTime = "";
mFilterEndTime = "";
mFilterType = -1;
viewBinding.refresh.setNoMoreData(false);
getWaterHistoryList();
});
viewBinding.refresh.setOnLoadMoreListener(layout -> {
mCurrentPage++;
getWaterHistoryList();
});
viewBinding.imgTimeFilter.setImageResource(
ThemeManager.isAppThemeLight(mContext) ?
R.mipmap.icon_triangle_down : R.mipmap.icon_white_triangle_down);
viewBinding.imgTypeFilter.setImageResource(
ThemeManager.isAppThemeLight(mContext) ?
R.mipmap.icon_triangle_down : R.mipmap.icon_white_triangle_down);
}
private void getWaterHistoryList(){
showLoadingDialog();
mPresenter.getWaterHistoryList(mCurrentPage,mFilterStartTime,mFilterEndTime,mFilterType);
}
private void initListener() {
setClick(viewBinding.linearTimeFilter);
setClick(viewBinding.linearTypeFilter);
setClick(viewBinding.includedNoresult.btnRefresh);
mAdapter.setOnItemChildClickListener(new BaseQuickAdapter.OnItemChildClickListener() {
@Override
public void onItemChildClick(BaseQuickAdapter adapter, View view, int position) {
switch (view.getId()){
case R.id.img_delete:
showDialogtext(null, false, false, "提示",
"确定删除该记录", "取消", "删除",
showDialogtext(null, false, false,
getString(R.string.tip_text),
getString(R.string.confirm_delete_record),
getString(R.string.cancel_text),
getString(R.string.confirm_text),
new OnDialogClick() {
@Override
public void onCancelClick() {
@@ -63,7 +111,8 @@ public class TabHistoryFragment extends BaseFragment<TabHistoryFragmentLayoutBin
@Override
public void onConfirmClick() {
mAdapter.remove(position);
showLoadingDialog();
mPresenter.deleteWaterHistory(recordList.get(position).getId(),position);
}
});
break;
@@ -93,14 +142,18 @@ public class TabHistoryFragment extends BaseFragment<TabHistoryFragmentLayoutBin
}
@Override
public void onDismiss(BasePopupView popupView) {
viewBinding.tvTimeFilter.setTextColor(mContext.getColor(R.color.color_222222));
viewBinding.imgTimeFilter.setImageResource(R.mipmap.icon_triangle_down);
viewBinding.tvTimeFilter.setTextColor(mContext.getColor(R.color.textPrimaryColor));
viewBinding.imgTimeFilter.setImageResource(
ThemeManager.isAppThemeLight(mContext) ?
R.mipmap.icon_triangle_down : R.mipmap.icon_white_triangle_down);
}
})
.asCustom(new CustomTimeFilterPopupView(getContext(), new CustomTimeFilterPopupView.OnClickListener() {
@Override
public void callBack(String startTime, String endTime) {
ToastUtil.showShort(mContext,startTime + "---" + endTime);
mFilterStartTime = startTime;
mFilterEndTime = endTime;
getWaterHistoryList();
}
}));
popupView.show();
@@ -121,25 +174,98 @@ public class TabHistoryFragment extends BaseFragment<TabHistoryFragmentLayoutBin
}
@Override
public void onDismiss(BasePopupView popupView) {
viewBinding.tvTypeFilter.setTextColor(mContext.getColor(R.color.color_222222));
viewBinding.imgTypeFilter.setImageResource(R.mipmap.icon_triangle_down);
viewBinding.tvTypeFilter.setTextColor(mContext.getColor(R.color.textPrimaryColor));
viewBinding.imgTypeFilter.setImageResource(
ThemeManager.isAppThemeLight(mContext) ?
R.mipmap.icon_triangle_down : R.mipmap.icon_white_triangle_down);
}
})
.asCustom(new CustomTypeFilterPopupView(getContext(), new CustomTypeFilterPopupView.OnClickListener() {
@Override
public void callBack(boolean mSelManual, boolean mSelAuto) {
if (mSelManual) {
mFilterType = 1;
} else if (mSelAuto) {
mFilterType = 0;
} else {
mFilterType = -1;
}
getWaterHistoryList();
}
}));
}, mFilterType));
typePopupView.show();
break;
case R.id.btn_refresh:
mCurrentPage = 1;
mFilterStartTime = "";
mFilterEndTime = "";
mFilterType = -1;
getWaterHistoryList();
break;
}
}
/**
* 获取浇水记录成功
* @param list
* @param total
*/
@Override
public void getHistoryListSuccess(List<WateringRecord> list, int total) {
hideDialogLoading();
List<WateringRecord> pageList = list == null ? new ArrayList<>() : list;
if (mCurrentPage == 1) {
viewBinding.refresh.finishRefresh(300);
recordList.clear(); // 只在刷新时清除
recordList = pageList;
} else {
viewBinding.refresh.finishLoadMore(300);
recordList.addAll(pageList);
}
mAdapter.setNewData(recordList);
// 4. 判断是否还有更多数据
if (mAdapter.getItemCount() >= total || pageList.size() == 0) {
// 使用 post 延迟调用,避免内部状态冲突导致的循环调用
viewBinding.refresh.postDelayed(() -> viewBinding.refresh.setNoMoreData(true), 300);
viewBinding.relNoMore.setVisibility(View.VISIBLE); // 自定义底部提示"暂无更多数据"
} else {
viewBinding.refresh.setNoMoreData(false);
viewBinding.relNoMore.setVisibility(View.GONE);
}
// 5. 控制空布局和内容显示
if (mAdapter.getItemCount() != 0) {
viewBinding.refresh.setVisibility(View.VISIBLE);
viewBinding.relNoresult.setVisibility(View.GONE);
} else {
viewBinding.refresh.setVisibility(View.GONE);
viewBinding.relNoresult.setVisibility(View.VISIBLE);
}
}
/**
* 删除历史记录成功
* @param bean
* @param position
*/
@Override
public void deleteHistorySuccess(BaseBean bean, int position) {
hideDialogLoading();
recordList.remove(position);
mAdapter.notifyItemRemoved(position);
}
@Override
public void getHistoryStatisticsSuccess(WaterStatisticsEntity entity) {
}
@Override
public HistoryPresenter createPresenter() {
return null;
return new HistoryPresenter(new HistoryImpl());
}
@Override
@@ -149,11 +275,14 @@ public class TabHistoryFragment extends BaseFragment<TabHistoryFragmentLayoutBin
@Override
public void showError(String message) {
hideDialogLoading();
ToastUtil.showShort(mContext,message);
}
@Override
public void logOut(BaseBean bean) {
}
}

View File

@@ -8,6 +8,7 @@ import com.chad.library.adapter.base.BaseQuickAdapter;
import com.chad.library.adapter.base.BaseViewHolder;
import com.ckkj.water.R;
import com.ckkj.water.history.entity.WateringRecord;
import com.ckkj.water.utils.time.ZYTimeUtils;
import java.util.List;
@@ -26,13 +27,16 @@ public class WateringHistoryAdapter extends BaseQuickAdapter<WateringRecord, Bas
@Override
protected void convert(BaseViewHolder helper, WateringRecord item) {
helper.setText(R.id.tv_device_name,item.getDeviceName());
helper.setText(R.id.tv_device_serial,item.getDeviceCode());
helper.setText(R.id.tv_device_serial,item.getDeviceNo());
helper.setText(R.id.tv_plan_time,mContext.getString(R.string.history_watering_adapter_time)
+ ":" + item.getStartTime() + "-" + item.getEndTime());
+ ":" + ZYTimeUtils.timeWithoutMillis(item.getStartTime())
+ "-" + ZYTimeUtils.timeWithoutMillis(item.getEndTime()));
helper.setText(R.id.tv_plan_duration,mContext.getString(R.string.device_work_times_title)
+ ":" + item.getDuration());
+ ":" + item.getDurationMin() + "min");
helper.setText(R.id.tv_plan_type,mContext.getString(R.string.tab_filter_type)
+ ":" + item.getTriggerType());
+ ":" + (item.getTriggerType().equals("0") ?
mContext.getString(R.string.history_filter_auto) :
mContext.getString(R.string.history_filter_manual)));
helper.addOnClickListener(R.id.img_delete);
}
}

View File

@@ -0,0 +1,34 @@
package com.ckkj.water.history.entity;
import java.io.Serializable;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @author fengxiaoyang
* @date 2026/6/2
* @description 历史记录数据统计
*/
@NoArgsConstructor
@Data
public class WaterStatisticsEntity implements Serializable {
/**
* schedule : 0
* manualNum : 2
* averageTime : 2
* count : 2
* weekCount : 1
* monCount : 1
* allTime : 5
*/
private int schedule;//排程次数
private int manualNum;//手动浇水次数
private int averageTime;//平均浇水时长
private int count;//总次数
private int weekCount;//本周浇水次数
private int monCount;//本月浇水次数
private int allTime;//总浇水时长
}

View File

@@ -8,7 +8,7 @@ import lombok.NoArgsConstructor;
/**
* @author fengxiaoyang
* @date 2026/5/15
* @description TODO: 描述该类的作用
* @description 浇水历史记录
*/
@NoArgsConstructor
@Data
@@ -29,4 +29,37 @@ public class WateringRecord implements Serializable {
private String endTime;
private String duration;
private String triggerType;
/**
* id : 2060156839441596420
* userId : 2056543507514097665
* deviceId : 2056641699765178369
* scheduleId : 1
* durationMin : 2
* zones : null
* createTime : 2026-06-09 09:30:41
*/
private String id;
private String userId;
private String deviceNo;
private String deviceId;
private String scheduleId;
private String durationMin;
private String zones;
private String createTime;
/**
* commandId : null
* scheduleId : 2062827585485807618
* zones : null
* remark : 设备离线,按排程自动补记
*/
private String commandId;
private String scheduleIdX;
private String zonesX;
private String remark;
}

View File

@@ -1,16 +1,34 @@
package com.ckkj.water.history.mvp;
import com.ckkj.water.base.IView;
import com.ckkj.water.history.entity.WaterStatisticsEntity;
import com.ckkj.water.history.entity.WateringRecord;
import com.ckkj.water.network.BaseBean;
import java.util.List;
import java.util.Map;
public class HistoryContract {
public interface CallBack<T> {
void success(T msg);
void success(T msg, int total);
void fail(String msg);
}
public interface DataModel{
//历史列表
void getHistoryList(Map<String, String> map, CallBack callBack);
//删除某一历史记录
void deleteHistory(String logID, CallBack callBack);
//浇水的数据统计
void getWateringStatistics(Map<String, String> map, CallBack callBack);
}
public interface HistoryView extends IView {
//历史记录成功
void getHistoryListSuccess(List<WateringRecord> msg, int total);
//删除历史记录成功
void deleteHistorySuccess(BaseBean msg, int position);
//数据统计成功
void getHistoryStatisticsSuccess(WaterStatisticsEntity entity);
}
}

View File

@@ -1,5 +1,127 @@
package com.ckkj.water.history.mvp;
import com.ckkj.water.history.entity.WaterStatisticsEntity;
import com.ckkj.water.history.entity.WateringRecord;
import com.ckkj.water.network.BaseBean;
import com.ckkj.water.network.NetWorkManager;
import java.util.List;
import java.util.Map;
import io.reactivex.Observer;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.annotations.NonNull;
import io.reactivex.disposables.Disposable;
import io.reactivex.schedulers.Schedulers;
public class HistoryImpl implements HistoryContract.DataModel{
/**
* 查询浇水历史
* @param map
* @param callBack
*/
@Override
public void getHistoryList(Map<String, String> map, HistoryContract.CallBack callBack) {
NetWorkManager.getRequest().waterLogList(NetWorkManager.getToken(), map)
.subscribeOn(Schedulers.io())
.unsubscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<BaseBean<List<WateringRecord>>>() {
@Override
public void onSubscribe(@NonNull Disposable d) {
}
@Override
public void onNext(@NonNull BaseBean<List<WateringRecord>> bean) {
if (bean.getCode() == 200) {
callBack.success(bean.getRows(),bean.getTotal());
}
}
@Override
public void onError(@NonNull Throwable e) {
callBack.fail(e.getMessage());
}
@Override
public void onComplete() {
}
});
}
/**
* 删除某一历史记录
* @param logID
* @param callBack
*/
@Override
public void deleteHistory(String logID, HistoryContract.CallBack callBack) {
try {
NetWorkManager.getRequest().deleteWaterLog(NetWorkManager.getToken(), logID)
.subscribeOn(Schedulers.io())
.unsubscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<BaseBean>() {
@Override
public void onSubscribe(@NonNull Disposable d) {
}
@Override
public void onNext(@NonNull BaseBean bean) {
if (bean.getCode() == 200) {
callBack.success(bean,0);
} else {
callBack.fail(bean.getMessage());
}
}
@Override
public void onError(@NonNull Throwable e) {
callBack.fail(e.getMessage());
}
@Override
public void onComplete() {
}
});
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 浇水的数据统计
* @param map
* @param callBack
*/
@Override
public void getWateringStatistics(Map<String, String> map, HistoryContract.CallBack callBack) {
NetWorkManager.getRequest().getDataStatistics(NetWorkManager.getToken())
.subscribeOn(Schedulers.io())
.unsubscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<BaseBean<WaterStatisticsEntity>>() {
@Override
public void onSubscribe(@NonNull Disposable d) {
}
@Override
public void onNext(@NonNull BaseBean<WaterStatisticsEntity> bean) {
if (bean.getCode() == 200) {
callBack.success(bean.getData(),0);
}
}
@Override
public void onError(@NonNull Throwable e) {
callBack.fail(e.getMessage());
}
@Override
public void onComplete() {
}
});
}
}

View File

@@ -1,6 +1,15 @@
package com.ckkj.water.history.mvp;
import android.text.TextUtils;
import com.ckkj.water.base.BasePresenter;
import com.ckkj.water.history.entity.WaterStatisticsEntity;
import com.ckkj.water.history.entity.WateringRecord;
import com.ckkj.water.network.BaseBean;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class HistoryPresenter extends BasePresenter<HistoryContract.HistoryView> {
private HistoryImpl impl;
@@ -8,4 +17,88 @@ public class HistoryPresenter extends BasePresenter<HistoryContract.HistoryView>
public HistoryPresenter(HistoryImpl impl) {
this.impl = impl;
}
/**
* 查询历史列表
* @param mCurrentPage
* @param mFilterStartTime
* @param mFilterEndTime
* @param mFilterType
*/
public void getWaterHistoryList(int mCurrentPage, String mFilterStartTime, String mFilterEndTime, int mFilterType) {
Map<String,String> map = new HashMap<>();
map.put("pageNum",mCurrentPage+"");
if(!TextUtils.isEmpty(mFilterStartTime)){
map.put("params[beginTime]", mFilterStartTime);
}
if(!TextUtils.isEmpty(mFilterStartTime)){
map.put("params[endTime]", mFilterEndTime);
}
if(mFilterType != -1){
map.put("triggerType",mFilterType+"");
}
impl.getHistoryList(map, new HistoryContract.CallBack<List<WateringRecord>>() {
@Override
public void success(List<WateringRecord> list,int total) {
if(HistoryPresenter.this.getView() != null){
HistoryPresenter.this.getView().getHistoryListSuccess(list,total);
}
}
@Override
public void fail(String msg) {
if(HistoryPresenter.this.getView() != null){
HistoryPresenter.this.getView().showMessage(msg);
}
}
});
}
/**
* 删除历史记录
* @param id
* @param position
*/
public void deleteWaterHistory(String id, int position) {
impl.deleteHistory(id, new HistoryContract.CallBack<BaseBean>() {
@Override
public void success(BaseBean bean, int total) {
if(HistoryPresenter.this.getView() != null){
HistoryPresenter.this.getView().deleteHistorySuccess(bean,position);
}
}
@Override
public void fail(String msg) {
if(HistoryPresenter.this.getView() != null){
HistoryPresenter.this.getView().showMessage(msg);
}
}
});
}
/**
* 获取浇水统计
*/
public void getWaterStatistic() {
impl.getWateringStatistics(null, new HistoryContract.CallBack<WaterStatisticsEntity>() {
@Override
public void success(WaterStatisticsEntity entity, int total) {
if(HistoryPresenter.this.getView() != null){
HistoryPresenter.this.getView().getHistoryStatisticsSuccess(entity);
}
}
@Override
public void fail(String msg) {
if(HistoryPresenter.this.getView() != null){
HistoryPresenter.this.getView().showMessage(msg);
}
}
});
}
}

View File

@@ -1,21 +1,32 @@
package com.ckkj.water.index;
import android.Manifest;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothManager;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.View;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.content.ContextCompat;
import com.ckkj.water.AppConfig;
import com.ckkj.water.R;
import com.ckkj.water.base.BaseFragment;
import com.ckkj.water.custom.view.CustomRefreshHeader;
import com.ckkj.water.databinding.IndexFragmentLayoutBinding;
import com.ckkj.water.ConstantUtil;
import com.ckkj.water.device.AddDeviceActivity;
import com.ckkj.water.device.DeviceControlActivity;
import com.ckkj.water.device.DeviceReNameActivity;
import com.ckkj.water.device.SelectWifiActivity;
import com.ckkj.water.index.adapter.DeviceAdapter;
import com.ckkj.water.index.entity.IndexDeviceEntity;
import com.ckkj.water.index.entity.WaterDeviceEntity;
import com.ckkj.water.index.mvp.IndexContract;
import com.ckkj.water.index.mvp.IndexImpl;
import com.ckkj.water.index.mvp.IndexPresenter;
@@ -27,6 +38,9 @@ import com.maning.mlkitscanner.scan.callback.act.MNScanCallback;
import com.scwang.smart.refresh.footer.ClassicsFooter;
import com.scwang.smart.refresh.layout.api.RefreshHeader;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.ArrayList;
import java.util.List;
@@ -36,13 +50,31 @@ public class IndexFragment extends BaseFragment<IndexFragmentLayoutBinding, Inde
implements IndexContract.IndexView , EasyPermissions.PermissionCallbacks{
private DeviceAdapter deviceAdapter;
private List<IndexDeviceEntity> devList = new ArrayList<>();
private List<WaterDeviceEntity> devList = new ArrayList<>();
private int mCurrentPage = 1;
// 扫码待配网设备
private WaterDeviceEntity pendingDeviceEntity = null;
// 蓝牙相关
private static final int REQUEST_EVENT_CODE_BLUETOOTH_PERMISSION = 10002;
private static final int REQUEST_ENABLE_BT = 10003;
private BluetoothAdapter bluetoothAdapter;
private boolean bluetoothReady = false;
@Override
protected void initArgs(Bundle bundle) {
}
@Override
protected void onResumeInitData() {
super.onResumeInitData();
if(AppConfig.USER_LOGIN){
showLoadingDialog();
mPresenter.getDevicesList(mCurrentPage);
}
}
@Override
public void initData(@Nullable Bundle savedInstanceState) {
// 设置自定义刷新头
@@ -57,9 +89,6 @@ public class IndexFragment extends BaseFragment<IndexFragmentLayoutBinding, Inde
mCurrentPage++;
mPresenter.getDevicesList(mCurrentPage);
});
showLoadingDialog();
mPresenter.getDevicesList(mCurrentPage);
}
@Override
@@ -77,6 +106,7 @@ public class IndexFragment extends BaseFragment<IndexFragmentLayoutBinding, Inde
private void initListener() {
setClick(viewBinding.imgScan);
setClick(viewBinding.imgAdd);
setClick(viewBinding.includedNoresult.btnRefresh);
}
private void setClick(View view) {
@@ -87,25 +117,36 @@ public class IndexFragment extends BaseFragment<IndexFragmentLayoutBinding, Inde
switch (v.getId()){
case R.id.img_scan:
//检测有无相机权限
String readPermission = Manifest.permission.CAMERA;
if(!hasRecordPermission(readPermission)){
getPermissionRequst(readPermission,"权限申请",
"智能浇水需要您的授权访问相机,并使用扫一扫",REQUEST_EVENT_CODE_10001);
if(checkBluetoothPermissions()){
//检测有无相机权限
String readPermission = Manifest.permission.CAMERA;
if(!hasRecordPermission(readPermission)){
getPermissionRequst(readPermission,
getString(R.string.permission_request_title),
getString(R.string.camera_permission_scan_desc),
REQUEST_EVENT_CODE_10001);
}else{
scanQrcode();
}
}else{
scanQrcode();
goTo(mContext, PermissionActivity.class,null);
}
break;
case R.id.img_add:
String permission = Manifest.permission.ACCESS_FINE_LOCATION;
boolean hasPermission = hasRecordPermission(permission);
if(!hasPermission){
goTo(mContext, PermissionActivity.class,null);
}else{
if(checkBluetoothPermissions()){
goTo(mContext, AddDeviceActivity.class,null);
}else{
goTo(mContext, PermissionActivity.class,null);
}
break;
case R.id.btn_refresh:
mCurrentPage = 1;
mPresenter.getDevicesList(mCurrentPage);
break;
}
}
@@ -117,15 +158,48 @@ public class IndexFragment extends BaseFragment<IndexFragmentLayoutBinding, Inde
switch (resultCode) {
case MNScanManager.RESULT_SUCCESS:
ArrayList<String> results = data.getStringArrayListExtra(MNScanManager.INTENT_KEY_RESULT_SUCCESS);
if(results != null){
ToastUtil.showShort(mContext,results.get(0).toString());
if (results == null || results.isEmpty()) {
ToastUtil.showShort(mContext, getString(R.string.qr_content_empty));
return;
}
String scanContent = results.get(0);
if (TextUtils.isEmpty(scanContent)) {
ToastUtil.showShort(mContext, getString(R.string.qr_content_empty));
return;
}
JSONObject json;
try {
json = new JSONObject(scanContent);
} catch (JSONException e) {
ToastUtil.showShort(mContext, getString(R.string.qr_format_error));
return;
}
try {
WaterDeviceEntity entity = new WaterDeviceEntity();
if(TextUtils.isEmpty(json.getString("mac"))
|| TextUtils.isEmpty(json.getString("name"))){
ToastUtil.showShort(mContext,getString(R.string.scan_correct_qr));
return;
}
entity.setMacAddress(json.getString("mac"));
entity.setDeviceName(json.getString("name"));
if(entity != null){
//这里拿到Mac地址需要去服务器查询当前Mac的绑定状态
mPresenter.bindDeviceStatus(entity);
}
} catch (JSONException e) {
ToastUtil.showShort(mContext, getString(R.string.scan_correct_qr));
return;
}
break;
case MNScanManager.RESULT_FAIL:
String resultError = data.getStringExtra(MNScanManager.INTENT_KEY_RESULT_ERROR);
break;
case MNScanManager.RESULT_CANCLE:
ToastUtil.showShort(mContext,"取消扫码");
ToastUtil.showShort(mContext,getString(R.string.cancel_scan));
break;
}
}
@@ -136,7 +210,9 @@ public class IndexFragment extends BaseFragment<IndexFragmentLayoutBinding, Inde
deviceAdapter = new DeviceAdapter(mContext,R.layout.index_device_list_item,devList);
viewBinding.rvDevices.setAdapter(deviceAdapter);
deviceAdapter.setOnItemClickListener((adapter, view, position) -> {
goTo(mContext, DeviceControlActivity.class,null);
Bundle bundle = new Bundle();
bundle.putSerializable("device_info",devList.get(position));
goTo(mContext, DeviceControlActivity.class,bundle);
});
}
@@ -144,24 +220,26 @@ public class IndexFragment extends BaseFragment<IndexFragmentLayoutBinding, Inde
* 获取设备列表成功
*/
@Override
public void getDeviceListSuccess(List<IndexDeviceEntity> list,int total) {
public void getDeviceListSuccess(List<WaterDeviceEntity> list, int total) {
hideDialogLoading();
viewBinding.refresh.finishRefresh(300);
viewBinding.refresh.finishLoadMore(300);
List<WaterDeviceEntity> pageList = list == null ? new ArrayList<>() : list;
if (mCurrentPage == 1) {
viewBinding.refresh.finishRefresh(300);
devList.clear(); // 只在刷新时清除
devList = list;
devList = pageList;
} else {
devList.addAll(list);
viewBinding.refresh.finishLoadMore(300);
devList.addAll(pageList);
}
deviceAdapter.setNewData(devList);
// 4. 判断是否还有更多数据
if (total == deviceAdapter.getItemCount() || list == null || list.size() == 0) {
// ✅ 告诉 SmartRefreshLayout 没有更多数据了
viewBinding.refresh.setNoMoreData(true);
viewBinding.relNoMore.setVisibility(View.VISIBLE); // 自定义底部提示暂无更多数据
if (deviceAdapter.getItemCount() >= total || pageList.size() == 0) {
// 使用 post 延迟调用,避免内部状态冲突导致的循环调用
viewBinding.refresh.postDelayed(() -> viewBinding.refresh.setNoMoreData(true), 300);
viewBinding.relNoMore.setVisibility(View.VISIBLE); // 自定义底部提示"暂无更多数据"
} else {
viewBinding.refresh.setNoMoreData(false); // 重置状态
viewBinding.refresh.setNoMoreData(false);
viewBinding.relNoMore.setVisibility(View.GONE);
}
@@ -175,6 +253,141 @@ public class IndexFragment extends BaseFragment<IndexFragmentLayoutBinding, Inde
}
}
/**
* 查询当前设备绑定状态
* @param entity
*/
@Override
public void queryDeviceBindStatusSuccess(WaterDeviceEntity entity) {
pendingDeviceEntity = entity.getBindDevice();
switch (entity.getBindDeviceStatus()){
case 200:
//该设备目前已经绑定了当前用户,直接跳转到设备控制页面
Bundle bundle = new Bundle();
bundle.putSerializable("device_info",entity.getBindDevice());
goTo(mContext, DeviceControlActivity.class,bundle);
break;
case 302:
case 305:
// 这是一台没有在mqtt中注册的设备需要通过蓝牙连接配网,(可理解为新设备,走蓝牙,配网)
// 先检查蓝牙权限和开启状态
checkBluetoothAndProceed();
break;
case 303:
//目前该设备,不属于该用户,需要提示解绑
showDialogtext(null,
false,
false,
getString(R.string.tip_text),
getString(R.string.device_binding_conflict_message),
"",
"",
new OnDialogClick() {
@Override
public void onCancelClick() {
}
@Override
public void onConfirmClick() {
}
});
break;
case 304:
//该设备目前在线已经在mqtt注册但是没有绑定用户需要跳转到绑定页面
Bundle bundleNoBind = new Bundle();
bundleNoBind.putSerializable("ble_device_entity", entity.getBindDevice());
goTo(mContext, DeviceReNameActivity.class, bundleNoBind);
break;
}
}
/**
* 检查蓝牙权限和开启状态,然后跳转配网
*/
private void checkBluetoothAndProceed() {
// 1. 检查蓝牙权限
if (!checkBluetoothPermissions()) {
return;
}
// 2. 检查蓝牙是否开启
if (!initBluetooth()) {
return;
}
// 3. 权限和状态都正常,跳转配网页面
goToDeviceProvisioning();
}
/**
* 检查蓝牙权限
*/
private boolean checkBluetoothPermissions() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
String[] permissions = {
Manifest.permission.BLUETOOTH_SCAN,
Manifest.permission.BLUETOOTH_CONNECT,
Manifest.permission.ACCESS_FINE_LOCATION
};
if (!hasRecordPermission(permissions)) {
return false;
}
} else {
// Android 12 以下需要位置权限
if (ContextCompat.checkSelfPermission(mContext, Manifest.permission.ACCESS_FINE_LOCATION)
!= PackageManager.PERMISSION_GRANTED) {
return false;
}
}
return true;
}
/**
* 初始化蓝牙适配器并检查蓝牙是否开启
* @return true 表示蓝牙已开启false 表示未开启或不支持
*/
private boolean initBluetooth() {
BluetoothManager bluetoothManager = (BluetoothManager) mContext.getSystemService(Context.BLUETOOTH_SERVICE);
if (bluetoothManager != null) {
bluetoothAdapter = bluetoothManager.getAdapter();
}
if (bluetoothAdapter == null) {
ToastUtil.showShort(mContext, "设备不支持蓝牙");
return false;
}
if (!bluetoothAdapter.isEnabled()) {
// 蓝牙未开启,请求开启
Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
return false;
}
bluetoothReady = true;
return true;
}
/**
* 跳转设备配网页面
*/
private void goToDeviceProvisioning() {
if (pendingDeviceEntity == null) {
ToastUtil.showShort(mContext, "设备信息异常");
return;
}
Bundle bundle = new Bundle();
bundle.putInt(ConstantUtil.ACTIVITY_NAVIGATE_FLAG, 100); // 100 = 来自扫码添加
bundle.putSerializable("ble_device_entity", pendingDeviceEntity);
goTo(mContext, SelectWifiActivity.class, bundle);
pendingDeviceEntity = null;
}
@Override
public void onDestroyView() {
@@ -195,15 +408,72 @@ public class IndexFragment extends BaseFragment<IndexFragmentLayoutBinding, Inde
public void logOut(BaseBean bean) {
}
@Override
public void onPermissionsGranted(int requestCode, @NonNull List<String> perms) {
hidePermissionDialog();
// if (requestCode == REQUEST_EVENT_CODE_10001) {
// scanQrcode();
// } else if (requestCode == REQUEST_EVENT_CODE_BLUETOOTH_PERMISSION) {
// // 蓝牙权限获取成功,检查蓝牙状态
// if (initBluetooth()) {
// goToDeviceProvisioning();
// }
// }
}
@Override
public void onPermissionsDenied(int requestCode, @NonNull List<String> perms) {
hidePermissionDialog();
if (requestCode == REQUEST_EVENT_CODE_BLUETOOTH_PERMISSION) {
ToastUtil.showShort(mContext, getString(R.string.bluetooth_permission_required));
}
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this);
hidePermissionDialog();
if (requestCode == REQUEST_EVENT_CODE_10001) {
// 相机权限回调
scanQrcode();
} else if (requestCode == REQUEST_EVENT_CODE_BLUETOOTH_PERMISSION) {
// 蓝牙权限回调
boolean allGranted = true;
for (int result : grantResults) {
if (result != PackageManager.PERMISSION_GRANTED) {
allGranted = false;
break;
}
}
if (allGranted) {
// 权限获取成功,检查蓝牙状态
if (initBluetooth()) {
goToDeviceProvisioning();
}
} else {
ToastUtil.showShort(mContext, getString(R.string.bluetooth_permission_required));
}
}
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == REQUEST_ENABLE_BT) {
if (resultCode == -1) { // RESULT_OK
ToastUtil.showShort(mContext, getString(R.string.bluetooth_enabled));
bluetoothReady = true;
if (pendingDeviceEntity != null) {
goToDeviceProvisioning();
}
} else {
ToastUtil.showShort(mContext, getString(R.string.enable_bluetooth_to_add_device));
}
}
}
}

View File

@@ -1,36 +1,64 @@
package com.ckkj.water.index.adapter;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import android.widget.ImageView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.recyclerview.widget.RecyclerView;
import com.chad.library.adapter.base.BaseQuickAdapter;
import com.chad.library.adapter.base.BaseViewHolder;
import com.ckkj.water.R;
import com.ckkj.water.index.entity.IndexDeviceEntity;
import com.ckkj.water.index.entity.WaterDeviceEntity;
import com.ckkj.water.utils.manager.PowerIconManage;
import com.esafirm.imagepicker.model.Image;
import java.util.List;
public class DeviceAdapter extends BaseQuickAdapter<IndexDeviceEntity, BaseViewHolder> {
public class DeviceAdapter extends BaseQuickAdapter<WaterDeviceEntity, BaseViewHolder> {
public DeviceAdapter(Context context, int layoutResId, @Nullable List<IndexDeviceEntity> data) {
public DeviceAdapter(Context context, int layoutResId, @Nullable List<WaterDeviceEntity> data) {
super(layoutResId, data);
this.mContext = context;
this.mData = data;
}
@Override
protected void convert(BaseViewHolder holder, IndexDeviceEntity item) {
protected void convert(BaseViewHolder holder, WaterDeviceEntity item) {
ImageView imgPower = holder.getView(R.id.img_battery);
View viewStatus = holder.getView(R.id.view_status_dot);
holder.setText(R.id.tv_device_name,item.getDeviceName());
holder.setText(R.id.tv_device_serial,item.getDeviceSn());
holder.setText(R.id.tv_device_status,"工作中");
holder.setText(R.id.tv_battery_level,"80");
//设备联网在线
if(item.getStatus().equals("1")){
switch (item.getWorkStatus()){
case "0"://待机
holder.setText(R.id.tv_device_status,mContext.getString(R.string.device_status_not_working));
holder.setTextColor(R.id.tv_device_status,mContext.getResources().getColor(R.color.color_999999));
viewStatus.setBackground(mContext.getResources().getDrawable(R.drawable.shape_status_dot_999999));
break;
case "1"://工作中
holder.setText(R.id.tv_device_status,mContext.getString(R.string.device_status_working));
holder.setTextColor(R.id.tv_device_status,mContext.getResources().getColor(R.color.color_24B326));
viewStatus.setBackground(mContext.getResources().getDrawable(R.drawable.shape_status_dot_green));
break;
}
}else{
holder.setText(R.id.tv_device_status,mContext.getString(R.string.device_status_offline));
holder.setTextColor(R.id.tv_device_status,mContext.getResources().getColor(R.color.color_E60000));
viewStatus.setBackground(mContext.getResources().getDrawable(R.drawable.shape_status_dot_red));
}
// if(item.getStatus().equals("1") || item.getStatus().equals("2")){
// }else{
// holder.setText(R.id.tv_device_status,mContext.getString(R.string.device_status_offline));
// holder.setTextColor(R.id.tv_device_status,mContext.getResources().getColor(R.color.color_999999));
// viewStatus.setBackground(mContext.getResources().getDrawable(R.drawable.shape_status_dot_999999));
// }
holder.setText(R.id.tv_battery_level,item.getPowerLevel());
imgPower.setImageResource(PowerIconManage.getInstance().getPowerIcon(Integer.parseInt(item.getPowerLevel())));
}

View File

@@ -1,45 +0,0 @@
package com.ckkj.water.index.entity;
import java.io.Serializable;
import lombok.Data;
import lombok.NoArgsConstructor;
@NoArgsConstructor
@Data
public class IndexDeviceEntity implements Serializable {
/**
* id : 2056638783822123010
* deviceNo : 1779175872972
* userId : 2056543507514097665
* deviceName : 50号设备
* deviceImg : null
* status : 0
* powerLevel : null
* powerLevelUpdatatime : null
* wifiName : 橙空科技WiFi
* wifiPassword : 12321212
* deviceEm : 213123123123
* deviceSn : sdfsd32423gdfgdf3
* fwVer : fwVer-56565644
* macAddress : 2E:8H:00:KK:N7
* expirationTime : null
*/
private String id;
private String deviceNo;
private String userId;
private String deviceName;
private Object deviceImg;
private String status;
private Object powerLevel;
private Object powerLevelUpdatatime;
private String wifiName;
private String wifiPassword;
private String deviceEm;
private String deviceSn;
private String fwVer;
private String macAddress;
private Object expirationTime;
}

View File

@@ -0,0 +1,84 @@
package com.ckkj.water.index.entity;
import java.io.Serializable;
import java.util.List;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
public class WaterDeviceEntity implements Serializable {
/**
* id : 2056638783822123010
* deviceNo : 1779175872972
* userId : 2056543507514097665
* deviceName : 50号设备
* deviceImg : null
* status : 0
* powerLevel : null
* powerLevelUpdatatime : null
* wifiName : 橙空科技WiFi
* wifiPassword : 12321212
* deviceEm : 213123123123
* deviceSn : sdfsd32423gdfgdf3
* fwVer : fwVer-56565644
* macAddress : 2E:8H:00:KK:N7
* expirationTime : null
*/
private String id;
private String deviceNo;
private String userId;
private String deviceName;
private Object deviceImg;
private String status;
private String workStatus;
private String powerLevel;
private String powerLevelUpdatatime;
private String wifiName;
private String wifiPassword;
private String deviceEm;
private String deviceSn;
private String fwVer;
private String macAddress;
private Object expirationTime;
private List<DeviceListBean> deviceList;
private int bindDeviceStatus;
private String bindDeviceStatusName;
private WaterDeviceEntity bindDevice;
private String startTime;
private String endTime;
@Data
@NoArgsConstructor
public static class DeviceListBean implements Serializable{
private String id;
private String deviceNo;
private String userId;
private String deviceName;
private Object deviceImg;
private String status;
private String workStatus;
private String powerLevel;
private Object powerLevelUpdatatime;
private String wifiName;
private String wifiPassword;
private String deviceEm;
private String deviceSn;
private String fwVer;
private String macAddress;
private Object expirationTime;
private int createDept;
private int createBy;
private String createTime;
private int updateBy;
private String updateTime;
private Object bindTokenHash;
private Object deviceImgX;
private String powerLevelUpdatatimeX;
private Object expirationTimeX;
private String checkStatus = "0";
}
}

View File

@@ -1,9 +1,7 @@
package com.ckkj.water.index.mvp;
import com.ckkj.water.base.IView;
import com.ckkj.water.index.entity.IndexDeviceEntity;
import com.ckkj.water.login.entity.LoginEntity;
import com.ckkj.water.network.BaseBean;
import com.ckkj.water.index.entity.WaterDeviceEntity;
import org.json.JSONObject;
@@ -25,10 +23,14 @@ public class IndexContract {
//获取设备列表
void getDeviceList(Map<String,String> map,CallBack callBack);
//查询二维码当前设备绑定状态
void queryDeviceBindStatus(JSONObject json, CallBack callBack);
}
public interface IndexView extends IView{
void getDeviceListSuccess(List<IndexDeviceEntity> list,int total);
void getDeviceListSuccess(List<WaterDeviceEntity> list, int total);
//查询二维码当前设备绑定状态
void queryDeviceBindStatusSuccess(WaterDeviceEntity entity);
}
}

View File

@@ -1,6 +1,6 @@
package com.ckkj.water.index.mvp;
import com.ckkj.water.index.entity.IndexDeviceEntity;
import com.ckkj.water.index.entity.WaterDeviceEntity;
import com.ckkj.water.network.BaseBean;
import com.ckkj.water.network.NetWorkManager;
@@ -28,13 +28,13 @@ public class IndexImpl implements IndexContract.DataModel{
.subscribeOn(Schedulers.io())
.unsubscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<BaseBean<List<IndexDeviceEntity>>>() {
.subscribe(new Observer<BaseBean<List<WaterDeviceEntity>>>() {
@Override
public void onSubscribe(@NonNull Disposable d) {
}
@Override
public void onNext(@NonNull BaseBean<List<IndexDeviceEntity>> bean) {
public void onNext(@NonNull BaseBean<List<WaterDeviceEntity>> bean) {
if (bean.getCode() == 200) {
callBack.success(bean.getRows(),bean.getTotal());
}
@@ -51,4 +51,44 @@ public class IndexImpl implements IndexContract.DataModel{
});
}
/**
* 查询当前设备绑定状态
* @param json
* @param callBack
*/
@Override
public void queryDeviceBindStatus(JSONObject json, IndexContract.CallBack callBack) {
try {
NetWorkManager.getRequest().bindDeviceStatus(NetWorkManager.getToken(),NetWorkManager.toRequestBody(json))
.subscribeOn(Schedulers.io())
.unsubscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<BaseBean<WaterDeviceEntity>>() {
@Override
public void onSubscribe(@NonNull Disposable d) {
}
@Override
public void onNext(@NonNull BaseBean<WaterDeviceEntity> bean) {
if (bean.getCode() == 200) {
callBack.success(bean.getData(),0);
} else {
callBack.fail(bean.getMessage());
}
}
@Override
public void onError(@NonNull Throwable e) {
callBack.fail(e.getMessage());
}
@Override
public void onComplete() {
}
});
} catch (Exception e) {
e.printStackTrace();
}
}
}

View File

@@ -1,7 +1,11 @@
package com.ckkj.water.index.mvp;
import com.ckkj.water.base.BasePresenter;
import com.ckkj.water.index.entity.IndexDeviceEntity;
import com.ckkj.water.index.entity.WaterDeviceEntity;
import com.ckkj.water.network.BaseBean;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.HashMap;
import java.util.List;
@@ -18,10 +22,10 @@ public class IndexPresenter extends BasePresenter<IndexContract.IndexView>{
* 查询设备列表
*/
public void getDevicesList(int mCurrentPage) {
mImpl.getDeviceList(new HashMap<>(), new IndexContract.CallBack<List<IndexDeviceEntity>>() {
mImpl.getDeviceList(new HashMap<>(), new IndexContract.CallBack<List<WaterDeviceEntity>>() {
@Override
public void success(List<IndexDeviceEntity> list, int total) {
public void success(List<WaterDeviceEntity> list, int total) {
if(IndexPresenter.this.getView() != null){
IndexPresenter.this.getView().getDeviceListSuccess(list,total);
}
@@ -35,4 +39,36 @@ public class IndexPresenter extends BasePresenter<IndexContract.IndexView>{
}
});
}
/**
* 绑定设备状态
* @param entity
*/
public void bindDeviceStatus(WaterDeviceEntity entity) {
try {
JSONObject json = new JSONObject();
json.put("macAddress",
entity.getMacAddress() == null ? "" : entity.getMacAddress().toLowerCase());
mImpl.queryDeviceBindStatus(json, new IndexContract.CallBack<WaterDeviceEntity>() {
@Override
public void success(WaterDeviceEntity bean, int total) {
bean.setMacAddress(entity.getMacAddress());
bean.setDeviceName(entity.getDeviceName());
if(IndexPresenter.this.getView() != null){
IndexPresenter.this.getView().queryDeviceBindStatusSuccess(bean);
}
}
@Override
public void fail(String msg) {
if(IndexPresenter.this.getView() != null){
IndexPresenter.this.getView().showError(msg);
}
}
});
} catch (JSONException e) {
throw new RuntimeException(e);
}
}
}

View File

@@ -2,8 +2,12 @@ package com.ckkj.water.login;
import android.os.Bundle;
import android.os.CountDownTimer;
import android.text.InputType;
import android.text.TextUtils;
import android.text.method.PasswordTransformationMethod;
import android.view.View;
import android.widget.EditText;
import android.widget.ImageView;
import com.ckkj.water.R;
import com.ckkj.water.base.BaseActivity;
@@ -13,6 +17,7 @@ import com.ckkj.water.login.mvp.LoginContract;
import com.ckkj.water.login.mvp.LoginImpl;
import com.ckkj.water.login.mvp.LoginPresenter;
import com.ckkj.water.network.BaseBean;
import com.ckkj.water.utils.manager.ThemeManager;
import com.ckkj.water.utils.number.PhoneNumberUtils;
import com.ckkj.water.utils.show.ToastUtil;
import com.gyf.immersionbar.ImmersionBar;
@@ -22,6 +27,10 @@ import com.gyf.immersionbar.ImmersionBar;
*/
public class ForgetPasswordActivity extends BaseActivity<RegisterLayoutBinding, LoginPresenter>
implements LoginContract.LoginView {
private boolean isPasswordVisible = false;
private boolean isConfirmPasswordVisible = false;
@Override
public LoginPresenter createPresenter() {
return new LoginPresenter(new LoginImpl());
@@ -36,8 +45,8 @@ public class ForgetPasswordActivity extends BaseActivity<RegisterLayoutBinding,
public void initData(Bundle savedInstanceState) {
super.initData(savedInstanceState);
ImmersionBar.with(this)
.statusBarColor(R.color.color_F9F9F9) // 设置状态栏颜色
.statusBarDarkFont(true) // 设置状态栏字体为黑色
.statusBarDarkFont(ThemeManager.isAppThemeLight(mContext)) // 白色状态栏图标
.navigationBarColor(R.color.color_gray_theme)
.titleBar(viewBinding.rlTitle)
.init();
viewBinding.includedTitle.tvTitle.setText(R.string.reset_psd_title);
@@ -49,6 +58,8 @@ public class ForgetPasswordActivity extends BaseActivity<RegisterLayoutBinding,
setClick(viewBinding.includedTitle.imgBack);
setClick(viewBinding.tvGetVerifiCode);
setClick(viewBinding.tvCommit);
setClick(viewBinding.imgPsdShowHide);
setClick(viewBinding.imgPsdShowHideAgin);
}
private void setClick(View view) {
@@ -71,17 +82,78 @@ public class ForgetPasswordActivity extends BaseActivity<RegisterLayoutBinding,
ToastUtil.showShort(mContext, getString(R.string.login_error_phone_invalid));
return;
}
cdTimer.start();
mPresenter.getPhoneCode(viewBinding.etAccount.getText().toString(),"");
// cdTimer.start();
break;
case R.id.tv_commit:
goTo(mContext, RegisterSuccessActivity.class,null);
if (TextUtils.isEmpty(viewBinding.etAccount.getText().toString())) {
ToastUtil.showShort(mContext, getString(R.string.login_error_phone_empty));
return;
}
if (!PhoneNumberUtils.checkPhoneNum(viewBinding.etAccount.getText().toString().trim()) &&
!PhoneNumberUtils.checkEmail(viewBinding.etAccount.getText().toString().trim())) {
ToastUtil.showShort(mContext, getString(R.string.login_error_phone_invalid));
return;
}
if (TextUtils.isEmpty(viewBinding.etVerfiCode.getText().toString())) {
ToastUtil.showShort(mContext, getString(R.string.login_error_code_empty));
return;
}
if (TextUtils.isEmpty(viewBinding.etInputPsd.getText().toString())) {
ToastUtil.showShort(mContext, getString(R.string.login_error_psd_empty));
return;
}
if (TextUtils.isEmpty(viewBinding.etInputPsdAgin.getText().toString())) {
ToastUtil.showShort(mContext, getString(R.string.login_error_psd_agin_empty));
return;
}
if(!(viewBinding.etInputPsd.getText().toString()).equals(
viewBinding.etInputPsdAgin.getText().toString())){
ToastUtil.showShort(mContext, getString(R.string.hint_input_psd_not_match));
return;
}
showLoadingDialog();
mPresenter.updatePsdByVerifyCode(viewBinding.etAccount.getText().toString(),
viewBinding.etVerfiCode.getText().toString(),
viewBinding.etInputPsd.getText().toString());
break;
case R.id.img_psd_show_hide:
togglePasswordVisibility(viewBinding.etInputPsd, viewBinding.imgPsdShowHide, isPasswordVisible);
isPasswordVisible = !isPasswordVisible;
break;
case R.id.img_psd_show_hide_agin:
togglePasswordVisibility(viewBinding.etInputPsdAgin, viewBinding.imgPsdShowHideAgin, isConfirmPasswordVisible);
isConfirmPasswordVisible = !isConfirmPasswordVisible;
break;
}
}
private void togglePasswordVisibility(EditText editText, ImageView imageView, boolean isVisible) {
if (editText == null || imageView == null) {
return;
}
private CountDownTimer cdTimer = new CountDownTimer(6000, 1000) {
if (isVisible) {
editText.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD);
editText.setTransformationMethod(PasswordTransformationMethod.getInstance());
imageView.setImageResource(R.mipmap.icon_psd_hide);
} else {
editText.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD);
editText.setTransformationMethod(null);
imageView.setImageResource(R.mipmap.icon_psd_show);
}
editText.setSelection(editText.getText().length());
}
private CountDownTimer cdTimer = new CountDownTimer(60000, 1000) {
@Override
public void onTick(long millisUntilFinished) {
viewBinding.tvGetVerifiCode.setText("(" + millisUntilFinished / 1000 + ") " + getString(R.string.login_resend));
@@ -101,6 +173,16 @@ public class ForgetPasswordActivity extends BaseActivity<RegisterLayoutBinding,
}
};
/**
* 修改密码成功
* @param bean
*/
@Override
public void updateUserPasswordSuccess(BaseBean bean) {
hideDialogLoading();
ToastUtil.showShort(mContext,getString(R.string.hint_update_psd_success));
finish();
}
@Override
public void registerSuccess(BaseBean bean) {
@@ -109,7 +191,9 @@ public class ForgetPasswordActivity extends BaseActivity<RegisterLayoutBinding,
@Override
public void getPhoneCodeSuccess(BaseBean bean) {
hideDialogLoading();
ToastUtil.showLong(mContext, getString(R.string.login_code_sent));
cdTimer.start();
}
@Override
@@ -117,6 +201,7 @@ public class ForgetPasswordActivity extends BaseActivity<RegisterLayoutBinding,
}
@Override
public void showError(String message) {
ToastUtil.showShort(mContext,message);

View File

@@ -10,18 +10,24 @@ import android.graphics.Typeface;
import android.os.Bundle;
import android.os.CountDownTimer;
import android.os.Handler;
import android.text.InputType;
import android.text.SpannableString;
import android.text.Spanned;
import android.text.TextPaint;
import android.text.TextUtils;
import android.text.method.LinkMovementMethod;
import android.text.method.PasswordTransformationMethod;
import android.text.style.ClickableSpan;
import android.view.View;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.core.content.ContextCompat;
import com.ckkj.water.mine.WebviewUserAgreement;
import com.ckkj.water.utils.manager.LanguageManager;
import com.google.gson.Gson;
import com.gyf.immersionbar.ImmersionBar;
import com.ckkj.water.AppConfig;
@@ -48,7 +54,8 @@ public class LoginActivity extends BaseActivity<LoginLayoutBinding, LoginPresent
implements LoginContract.LoginView {
private boolean mYinsiConfirm = false;
//当前登录方式 验证码100 密码 200
private boolean isPasswordVisible = false;
//当前登录方式 验证码100 密码 200..
private static int LOGIN_TYPE_STATUS_CODE = 100;
@Override
@@ -79,6 +86,9 @@ public class LoginActivity extends BaseActivity<LoginLayoutBinding, LoginPresent
setClick(viewBinding.tvLanguage);
setClick(viewBinding.tvResetPsd);
setClick(viewBinding.checkboxRead);
setClick(viewBinding.imgPsdShowHide);
setClick(viewBinding.btn133);
setClick(viewBinding.btn151);
}
private void setClick(View view) {
@@ -86,65 +96,109 @@ public class LoginActivity extends BaseActivity<LoginLayoutBinding, LoginPresent
}
private void setupAgreementText() {
//勾选协议,增加点击区域
ClickUtil.addClickPart(viewBinding.checkboxRead,100);
ClickUtil.addClickPart(viewBinding.checkboxRead, 100);
TextView tvAgreement = findViewById(R.id.tv_agreement_full);
String content = "我已经阅读并同意智能浇灌《用户协议》、《隐私政策》";
String content = getString(R.string.agree_user_policy);
String userAgreementText = getString(R.string.user_agreement);
String privacyPolicyText = getString(R.string.privacy_policy);
SpannableString spannableString = new SpannableString(content);
// 设置“用户协议”可点击
ClickableSpan userAgreementSpan = new ClickableSpan() {
addClickableSpan(
spannableString,
content,
userAgreementText,
() -> {
// 跳转用户协议
Bundle bundle = new Bundle();
bundle.putInt("from_requse_code", WebviewUserAgreement.AGREEMENT_CODE);
goToWihoutNoPresent(mContext, WebviewUserAgreement.class,bundle);
}
);
addClickableSpan(
spannableString,
content,
privacyPolicyText,
() -> {
// 跳转隐私政策
Bundle bundleYS = new Bundle();
bundleYS.putInt("from_requse_code",WebviewUserAgreement.PRIVACY_CODE);
goToWihoutNoPresent(mContext, WebviewUserAgreement.class,bundleYS);
}
);
tvAgreement.setText(spannableString);
tvAgreement.setMovementMethod(LinkMovementMethod.getInstance());
tvAgreement.setHighlightColor(Color.TRANSPARENT);
}
private void addClickableSpan(
SpannableString spannableString,
String content,
String target,
Runnable action) {
int start = content.indexOf(target);
if (start < 0) {
return;
}
int end = start + target.length();
ClickableSpan clickableSpan = new ClickableSpan() {
@Override
public void onClick(@NonNull View widget) {
// 跳转用户协议
// Bundle bundle = new Bundle();
// bundle.putInt("from_requse_code", WebviewUserAgreement.AGREEMENT_CODE);
// goToWihoutNoPresent(mContext, WebviewUserAgreement.class,bundle);
ToastUtil.showShort(mContext,"用户协议");
action.run();
}
@Override
public void updateDrawState(@NonNull TextPaint ds) {
super.updateDrawState(ds);
ds.setColor(ContextCompat.getColor(mContext, R.color.color_zhu)); // 设置颜色
ds.setUnderlineText(false); // 去掉下划线
}
};
int start1 = content.indexOf("《用户协议》");
int end1 = start1 + "《用户协议》".length();
spannableString.setSpan(userAgreementSpan, start1, end1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
// 设置“隐私政策”可点击
ClickableSpan privacyPolicySpan = new ClickableSpan() {
@Override
public void onClick(@NonNull View widget) {
// 跳转隐私政策
// Bundle bundleYS = new Bundle();
// bundleYS.putInt("from_requse_code",WebviewUserAgreement.PRIVACY_CODE);
// goToWihoutNoPresent(mContext, WebviewUserAgreement.class,bundleYS);
ToastUtil.showShort(mContext,"跳转隐私政策");
}
ds.setColor(
ContextCompat.getColor(
mContext,
R.color.color_zhu
)
);
@Override
public void updateDrawState(@NonNull TextPaint ds) {
super.updateDrawState(ds);
ds.setColor(ContextCompat.getColor(mContext, R.color.color_zhu)); // 设置颜色
ds.setUnderlineText(false);
}
};
int start2 = content.indexOf("《隐私政策》");
int end2 = start2 + "《隐私政策》".length();
spannableString.setSpan(privacyPolicySpan, start2, end2, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
tvAgreement.setText(spannableString);
tvAgreement.setMovementMethod(LinkMovementMethod.getInstance()); // 开启点击事件
tvAgreement.setHighlightColor(Color.TRANSPARENT);
spannableString.setSpan(
clickableSpan,
start,
end,
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
);
}
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn_133:
showLoadingDialog();
mPresenter.loginBySmsCode("password",
"13305376054",
"",
"000000");
break;
case R.id.btn_151:
showLoadingDialog();
mPresenter.loginBySmsCode("password",
"15192412330",
"",
"000000");
break;
case R.id.checkbox_read:
if(mYinsiConfirm){
mYinsiConfirm = false;
@@ -206,30 +260,30 @@ public class LoginActivity extends BaseActivity<LoginLayoutBinding, LoginPresent
break;
case R.id.tv_language:
new XPopup.Builder(mContext).asBottomList(
"选择语言",
new String[]{"中文", "English"},
new int[]{R.mipmap.ic_launcher, R.mipmap.ic_launcher},
0,
new OnSelectListener() {
@Override
public void onSelect(int position, String text) {
ToastUtil.showShort(mContext,text);
}
},
R.layout.select_language_layout,
R.layout.select_language_item
).show();
new XPopup.Builder(mContext)
.isDestroyOnDismiss(true)
.dismissOnBackPressed(true)
.dismissOnTouchOutside(true)
.asBottomList(
getString(R.string.change_language),
LanguageManager.getLanguageDisplayNames(mContext),
LanguageManager.getLanguageIcons(),
LanguageManager.getCurrentLanguageIndex(),
new OnSelectListener() {
@Override
public void onSelect(int position, String text) {
LanguageManager.switchLanguageByIndex(position, LoginActivity.this);
}
},
R.layout.select_language_layout,
R.layout.select_language_item
).show();
break;
// case R.id.checkbox_read:
// if (mYinsiConfirm) {
// mYinsiConfirm = false;
// viewBinding.checkboxRead.setChecked(false);
// } else {
// mYinsiConfirm = true;
// viewBinding.checkboxRead.setChecked(true);
// }
// break;
case R.id.tv_reset_psd ://重置密码
goTo(mContext, ForgetPasswordActivity.class,null);
break;
case R.id.tv_login:
if (TextUtils.isEmpty(viewBinding.etAccount.getText().toString())) {
ToastUtil.showShort(mContext, getString(R.string.login_error_phone_empty));
@@ -272,11 +326,15 @@ public class LoginActivity extends BaseActivity<LoginLayoutBinding, LoginPresent
// new Handler().postDelayed(() -> hideDialogLoading(), 1000);
break;
case R.id.img_psd_show_hide:
togglePasswordVisibility();
break;
}
}
private CountDownTimer cdTimer = new CountDownTimer(6000, 1000) {
private CountDownTimer cdTimer = new CountDownTimer(60000, 1000) {
@Override
public void onTick(long millisUntilFinished) {
viewBinding.tvGetVerifiCode.setText("(" + millisUntilFinished / 1000 + ") " + getString(R.string.login_resend));
@@ -296,6 +354,31 @@ public class LoginActivity extends BaseActivity<LoginLayoutBinding, LoginPresent
}
};
private void togglePasswordVisibility() {
EditText etPassword = viewBinding.etInputPsd;
ImageView ivToggle = viewBinding.imgPsdShowHide;
if (etPassword == null || ivToggle == null) {
return;
}
if (isPasswordVisible) {
// 隐藏密码
etPassword.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD);
etPassword.setTransformationMethod(PasswordTransformationMethod.getInstance());
ivToggle.setImageResource(R.mipmap.icon_psd_hide);
} else {
// 显示密码
etPassword.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD);
etPassword.setTransformationMethod(null);
ivToggle.setImageResource(R.mipmap.icon_psd_show);
}
// 保持光标位置
etPassword.setSelection(etPassword.getText().length());
isPasswordVisible = !isPasswordVisible;
}
@Override
public void registerSuccess(BaseBean bean) {
@@ -304,8 +387,8 @@ public class LoginActivity extends BaseActivity<LoginLayoutBinding, LoginPresent
@Override
public void getPhoneCodeSuccess(BaseBean bean) {
hideDialogLoading();
ToastUtil.showLong(mContext, getString(R.string.login_code_sent) + ":" + bean.getDataString());
// cdTimer.start();
ToastUtil.showLong(mContext, getString(R.string.login_code_sent));
cdTimer.start();
}
@Override
@@ -326,6 +409,11 @@ public class LoginActivity extends BaseActivity<LoginLayoutBinding, LoginPresent
}, 200);
}
@Override
public void updateUserPasswordSuccess(BaseBean bean) {
}
@Override
public int getLayoutResId(Bundle savedInstanceState) {
return 0;

View File

@@ -2,8 +2,12 @@ package com.ckkj.water.login;
import android.os.Bundle;
import android.os.CountDownTimer;
import android.text.InputType;
import android.text.TextUtils;
import android.text.method.PasswordTransformationMethod;
import android.view.View;
import android.widget.EditText;
import android.widget.ImageView;
import com.ckkj.water.R;
import com.ckkj.water.base.BaseActivity;
@@ -13,6 +17,8 @@ import com.ckkj.water.login.mvp.LoginContract;
import com.ckkj.water.login.mvp.LoginImpl;
import com.ckkj.water.login.mvp.LoginPresenter;
import com.ckkj.water.network.BaseBean;
import com.ckkj.water.utils.FastClickUtils;
import com.ckkj.water.utils.manager.ThemeManager;
import com.ckkj.water.utils.number.PhoneNumberUtils;
import com.ckkj.water.utils.show.ToastUtil;
import com.gyf.immersionbar.ImmersionBar;
@@ -21,6 +27,10 @@ import me.jessyan.autosize.internal.CustomAdapt;
public class RegisterActivity extends BaseActivity<RegisterLayoutBinding, LoginPresenter>
implements LoginContract.LoginView {
private boolean isPasswordVisible = false;
private boolean isConfirmPasswordVisible = false;
@Override
public LoginPresenter createPresenter() {
return new LoginPresenter(new LoginImpl());
@@ -35,8 +45,8 @@ public class RegisterActivity extends BaseActivity<RegisterLayoutBinding, LoginP
public void initData(Bundle savedInstanceState) {
super.initData(savedInstanceState);
ImmersionBar.with(this)
.statusBarColor(R.color.color_F9F9F9) // 设置状态栏颜色
.statusBarDarkFont(true) // 设置状态栏字体为黑色
.statusBarDarkFont(ThemeManager.isAppThemeLight(mContext)) // 白色状态栏图标
.navigationBarColor(R.color.color_gray_theme)
.titleBar(viewBinding.rlTitle)
.init();
viewBinding.includedTitle.tvTitle.setText(R.string.register_title);
@@ -47,6 +57,8 @@ public class RegisterActivity extends BaseActivity<RegisterLayoutBinding, LoginP
setClick(viewBinding.includedTitle.imgBack);
setClick(viewBinding.tvGetVerifiCode);
setClick(viewBinding.tvCommit);
setClick(viewBinding.imgPsdShowHide);
setClick(viewBinding.imgPsdShowHideAgin);
}
private void setClick(View view) {
@@ -60,6 +72,11 @@ public class RegisterActivity extends BaseActivity<RegisterLayoutBinding, LoginP
break;
case R.id.tv_get_verifi_code:
// 防止快速点击
if (!FastClickUtils.onclickTimes()) {
return;
}
if (TextUtils.isEmpty(viewBinding.etAccount.getText().toString())) {
ToastUtil.showShort(mContext, getString(R.string.login_error_phone_empty));
return;
@@ -71,10 +88,14 @@ public class RegisterActivity extends BaseActivity<RegisterLayoutBinding, LoginP
}
//发送短信
mPresenter.getPhoneCode(viewBinding.etAccount.getText().toString(),"");
// cdTimer.start();
break;
case R.id.tv_commit:
// 防止快速点击
if (!FastClickUtils.onclickTimes()) {
return;
}
if (TextUtils.isEmpty(viewBinding.etAccount.getText().toString())) {
ToastUtil.showShort(mContext, getString(R.string.login_error_phone_empty));
return;
@@ -85,11 +106,7 @@ public class RegisterActivity extends BaseActivity<RegisterLayoutBinding, LoginP
return;
}
if (TextUtils.isEmpty(viewBinding.etVerfiCode.getText().toString())) {
ToastUtil.showShort(mContext, getString(R.string.login_error_phone_empty));
return;
}
if (TextUtils.isEmpty(viewBinding.etVerfiCode.getText().toString())) {
ToastUtil.showShort(mContext, getString(R.string.login_error_phone_empty));
ToastUtil.showShort(mContext, getString(R.string.login_error_code_empty));
return;
}
@@ -113,11 +130,21 @@ public class RegisterActivity extends BaseActivity<RegisterLayoutBinding, LoginP
viewBinding.etVerfiCode.getText().toString(),
viewBinding.etInputPsd.getText().toString());
break;
case R.id.img_psd_show_hide:
togglePasswordVisibility(viewBinding.etInputPsd, viewBinding.imgPsdShowHide, isPasswordVisible);
isPasswordVisible = !isPasswordVisible;
break;
case R.id.img_psd_show_hide_agin:
togglePasswordVisibility(viewBinding.etInputPsdAgin, viewBinding.imgPsdShowHideAgin, isConfirmPasswordVisible);
isConfirmPasswordVisible = !isConfirmPasswordVisible;
break;
}
}
private CountDownTimer cdTimer = new CountDownTimer(6000, 1000) {
private CountDownTimer cdTimer = new CountDownTimer(60000, 1000) {
@Override
public void onTick(long millisUntilFinished) {
viewBinding.tvGetVerifiCode.setText("(" + millisUntilFinished / 1000 + ") " + getString(R.string.login_resend));
@@ -138,16 +165,40 @@ public class RegisterActivity extends BaseActivity<RegisterLayoutBinding, LoginP
};
@Override
public void registerSuccess(BaseBean bean) {
hideDialogLoading();
ToastUtil.showShort(mContext,"注册成功");
finish();
private void togglePasswordVisibility(EditText editText, ImageView imageView, boolean isVisible) {
if (editText == null || imageView == null) {
return;
}
if (isVisible) {
editText.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD);
editText.setTransformationMethod(PasswordTransformationMethod.getInstance());
imageView.setImageResource(R.mipmap.icon_psd_hide);
} else {
editText.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD);
editText.setTransformationMethod(null);
imageView.setImageResource(R.mipmap.icon_psd_show);
}
editText.setSelection(editText.getText().length());
}
@Override
public void getPhoneCodeSuccess(BaseBean bean) {
public void registerSuccess(BaseBean bean) {
hideDialogLoading();
ToastUtil.showShort(mContext,getString(R.string.register_success_title));
finish();
}
/**
* 获取验证码成功
* @param bean
*/
@Override
public void getPhoneCodeSuccess(BaseBean bean) {
hideDialogLoading();
ToastUtil.showShort(mContext,getString(R.string.verification_code_sent));
cdTimer.start();
}
@Override
@@ -155,6 +206,15 @@ public class RegisterActivity extends BaseActivity<RegisterLayoutBinding, LoginP
}
/**
* 修改密码成功
* @param bean
*/
@Override
public void updateUserPasswordSuccess(BaseBean bean) {
hideDialogLoading();
}
@Override
public void showError(String message) {
hideDialogLoading();

View File

@@ -13,6 +13,7 @@ import com.ckkj.water.login.entity.LoginEntity;
import com.ckkj.water.login.mvp.LoginContract;
import com.ckkj.water.login.mvp.LoginImpl;
import com.ckkj.water.login.mvp.LoginPresenter;
import com.ckkj.water.main.activity.MainActivity;
import com.ckkj.water.network.BaseBean;
import com.ckkj.water.permission.PermissionActivity;
import com.ckkj.water.utils.show.ToastUtil;
@@ -45,7 +46,7 @@ public class RegisterSuccessActivity extends BaseActivity<RegisterSuccessLayoutB
viewBinding.tvCommit.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
goTo(mContext, PermissionActivity.class,null);
goTo(mContext, MainActivity.class,null);
}
});
}
@@ -94,6 +95,11 @@ public class RegisterSuccessActivity extends BaseActivity<RegisterSuccessLayoutB
}
@Override
public void updateUserPasswordSuccess(BaseBean bean) {
}
@Override
public void showError(String message) {

View File

@@ -22,11 +22,18 @@ public class LoginContract {
public interface DataModel{
//手机验证码登录
void register(JSONObject json, CallBack callBack);
//获取手机验证码
void getPhoneCode(Map<String,Object> map, CallBack callBack);
//手机验证码登录
void loginBySmsCode(JSONObject json, CallBack callBack);
//通过账户+验证码 修改密码
void updatePsdByVerifyCode(JSONObject json, CallBack callBack);
//退出登录
void logout(JSONObject json, CallBack callBack);
//注销账号--发送验证码
void logoffAccountCode(Map<String,Object> map, CallBack callBack);
//注销账号--确认注销
void logoffAccount(JSONObject json, CallBack callBack);
}
public interface LoginView extends IView{
@@ -35,5 +42,7 @@ public class LoginContract {
void getPhoneCodeSuccess(BaseBean bean);
//验证码登录成功
void loginBySmsCodeSuccess(LoginEntity entity);
//通过验证码修改密码成功
void updateUserPasswordSuccess(BaseBean bean);
}
}

View File

@@ -105,6 +105,93 @@ public class LoginImpl implements LoginContract.DataModel {
}
}
/**
* 注销账号--发送验证码
* @param map
* @param callBack
*/
@Override
public void logoffAccountCode(Map<String, Object> map, LoginContract.CallBack callBack) {
try {
NetWorkManager.getRequest().logoffAccountCode(NetWorkManager.getToken())
.subscribeOn(Schedulers.io())
.unsubscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<BaseBean>() {
@Override
public void onSubscribe(@NonNull Disposable d) {
}
@Override
public void onNext(@NonNull BaseBean bean) {
if (bean.getCode() == 200) {
callBack.success(bean);
} else {
callBack.fail(bean.getMessage());
}
}
@Override
public void onError(@NonNull Throwable e) {
callBack.fail(e.getMessage());
}
@Override
public void onComplete() {
}
});
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 注销账号--确认
* @param json
* @param callBack
*/
@Override
public void logoffAccount(JSONObject json, LoginContract.CallBack callBack) {
try {
NetWorkManager.getRequest().confirmLogiffAccount(NetWorkManager.getToken(), NetWorkManager.toRequestBody(json))
.subscribeOn(Schedulers.io())
.unsubscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<BaseBean>() {
@Override
public void onSubscribe(@NonNull Disposable d) {
}
@Override
public void onNext(@NonNull BaseBean bean) {
if (bean.getCode() == 200) {
callBack.success(bean);
} else {
callBack.fail(bean.getMessage());
}
}
@Override
public void onError(@NonNull Throwable e) {
callBack.fail(e.getMessage());
}
@Override
public void onComplete() {
}
});
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 使用验证码登录
* @param json
* @param callBack
*/
@Override
public void loginBySmsCode(JSONObject json, LoginContract.CallBack callBack) {
try {
@@ -141,4 +228,86 @@ public class LoginImpl implements LoginContract.DataModel {
e.printStackTrace();
}
}
/**
* 通过验证码修改密码
* @param json
* @param callBack
*/
@Override
public void updatePsdByVerifyCode(JSONObject json, LoginContract.CallBack callBack) {
try {
NetWorkManager.getRequest().updatePasswordByVerifyCode(NetWorkManager.getToken(),NetWorkManager.toRequestBody(json))
.subscribeOn(Schedulers.io())
.unsubscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<BaseBean>() {
@Override
public void onSubscribe(@NonNull Disposable d) {
}
@Override
public void onNext(@NonNull BaseBean bean) {
if (bean.getCode() == 200) {
callBack.success(bean);
} else {
callBack.fail(bean.getMessage());
}
}
@Override
public void onError(@NonNull Throwable e) {
callBack.fail(e.getMessage());
}
@Override
public void onComplete() {
}
});
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 退出登录
* @param json
* @param callBack
*/
@Override
public void logout(JSONObject json, LoginContract.CallBack callBack) {
try {
NetWorkManager.getRequest().logout(NetWorkManager.toRequestBody(json))
.subscribeOn(Schedulers.io())
.unsubscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<BaseBean>() {
@Override
public void onSubscribe(@NonNull Disposable d) {
}
@Override
public void onNext(@NonNull BaseBean bean) {
if (bean.getCode() == 200) {
callBack.success(bean.getData());
} else {
callBack.fail(bean.getMessage());
}
}
@Override
public void onError(@NonNull Throwable e) {
callBack.fail(e.getMessage());
}
@Override
public void onComplete() {
}
});
} catch (Exception e) {
e.printStackTrace();
}
}
}

View File

@@ -3,6 +3,8 @@ package com.ckkj.water.login.mvp;
import com.ckkj.water.AppConfig;
import com.ckkj.water.base.BasePresenter;
import com.ckkj.water.login.entity.LoginEntity;
import com.ckkj.water.mine.mvp.MineContract;
import com.ckkj.water.mine.mvp.MinePresenter;
import com.ckkj.water.network.BaseBean;
import org.json.JSONException;
@@ -146,4 +148,35 @@ public class LoginPresenter extends BasePresenter<LoginContract.LoginView> {
}
/**
* 通过验证码修改密码
* @param account
* @param code
* @param psd
*/
public void updatePsdByVerifyCode(String account, String code, String psd) {
try {
JSONObject json = new JSONObject();
json.put("userName", account);
json.put("code", code);
json.put("password", psd);
mImpl.updatePsdByVerifyCode(json, new LoginContract.CallBack<BaseBean>() {
@Override
public void success(BaseBean bean) {
if(LoginPresenter.this.getView() != null){
LoginPresenter.this.getView().updateUserPasswordSuccess(bean);
}
}
@Override
public void fail(String msg) {
if(LoginPresenter.this.getView() != null){
LoginPresenter.this.getView().showError(msg);
}
}
});
} catch (JSONException e) {
throw new RuntimeException(e);
}
}
}

View File

@@ -1,7 +1,7 @@
package com.ckkj.water.main;
import com.ckkj.water.base.IView;
import com.ckkj.water.base.entity.MineUserInfoBean;
import com.ckkj.water.mine.entity.MineUserInfoBean;
import com.ckkj.water.main.entity.CheckVersionEntity;
import com.ckkj.water.network.BaseBean;
@@ -12,7 +12,7 @@ import java.util.Map;
public interface MainContract {
interface DataModel{
//新版本检测
void checkAppVersionCode(JSONObject json, CallBack callBack);
void checkAppVersionCode(Map<String,String> map, CallBack callBack);
//运势
void getYunshiData(Map<String,Object> map, CallBack callBack);
}

View File

@@ -20,13 +20,13 @@ public class MainImpl implements MainContract.DataModel{
/**
* 检测新版本
* @param jsonObject
* @param map
* @param callBack
*/
@Override
public void checkAppVersionCode(JSONObject jsonObject, MainContract.CallBack callBack) {
public void checkAppVersionCode(Map<String,String> map, MainContract.CallBack callBack) {
try {
NetWorkManager.getRequest().checkVersionCode(NetWorkManager.getToken(),NetWorkManager.toRequestBody(jsonObject))
NetWorkManager.getRequest().checkVersionCode(NetWorkManager.getToken(),map)
.subscribeOn(Schedulers.io())
.unsubscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())

View File

@@ -1,11 +1,8 @@
package com.ckkj.water.main;
import com.ckkj.water.BuildConfig;
import com.ckkj.water.base.BasePresenter;
import com.ckkj.water.base.entity.MineUserInfoBean;
import com.ckkj.water.login.mvp.LoginContract;
import com.ckkj.water.main.entity.CheckVersionEntity;
import com.ckkj.water.mine.mvp.MineImpl;
import com.ckkj.water.network.BaseBean;
import org.json.JSONObject;
@@ -24,8 +21,10 @@ public class MainPresenter extends BasePresenter<MainContract.MainView> {
* 获取用户信息
*/
public void checkNewVersion() {
JSONObject json = new JSONObject();
mainImpl.checkAppVersionCode(json, new MainContract.CallBack<CheckVersionEntity>() {
Map<String,String> map = new HashMap<>();
map.put("platform","android");
map.put("currentVersion", BuildConfig.APP_VERSION_NAME);
mainImpl.checkAppVersionCode(map, new MainContract.CallBack<CheckVersionEntity>() {
@Override
public void success(CheckVersionEntity bean) {
if( MainPresenter.this.getView() != null){

View File

@@ -1,5 +1,9 @@
package com.ckkj.water.main.activity;
import static com.ckkj.water.ConstantUtil.POST_NOTIFICATIONS_PERMISSION_CODE;
import static com.ckkj.water.ConstantUtil.WRITE_FILE_PERMISSON_CPDE;
import android.Manifest;
import android.content.Intent;
import android.os.Bundle;
import android.view.KeyEvent;
@@ -18,13 +22,12 @@ import com.ckkj.water.mine.MineCenterFragment;
import com.ckkj.water.plan.WaterPlanFragment;
import com.ckkj.water.utils.manager.ThemeManager;
import com.gyf.immersionbar.ImmersionBar;
import com.ckkj.water.AppConfig;
import com.ckkj.water.ConstantUtil;
import com.ckkj.water.EventMessage;
import com.ckkj.water.R;
import com.ckkj.water.adapter.ViewPageAdapter;
import com.ckkj.water.base.BaseActivity;
import com.ckkj.water.base.entity.MineUserInfoBean;
import com.ckkj.water.mine.entity.MineUserInfoBean;
import com.ckkj.water.databinding.MainActivityLayoutBinding;
import com.ckkj.water.dialog.DialogAppUpdate;
import com.ckkj.water.main.MainContract;
@@ -33,7 +36,6 @@ import com.ckkj.water.main.MainPresenter;
import com.ckkj.water.main.entity.CheckVersionEntity;
import com.ckkj.water.network.BaseBean;
import com.ckkj.water.utils.AppInfoUtil;
import com.ckkj.water.utils.dataUtil.SharePreUtil;
import com.ckkj.water.utils.manager.ActivityManager;
import com.ckkj.water.utils.manager.WaterUserInfoManager;
import com.ckkj.water.utils.show.ToastUtil;
@@ -105,7 +107,7 @@ public class MainActivity extends BaseActivity<MainActivityLayoutBinding, MainPr
@Override
public void initData(Bundle savedInstanceState) {
super.initData(savedInstanceState);
// mPresenter.checkNewVersion();
mPresenter.checkNewVersion();
// 清空Fragment列表避免状态恢复问题
mFragmentList.clear();
mFragmentList.add(new IndexFragment());
@@ -310,9 +312,25 @@ public class MainActivity extends BaseActivity<MainActivityLayoutBinding, MainPr
public void onRequestPermissionsResult(int requestCode, @NonNull @NotNull String[] permissions, @NonNull @NotNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this);
hidePermissionDialog();
if(requestCode == WRITE_FILE_PERMISSON_CPDE){
if(mUpdateDialog != null && grantResults.length > 0 && grantResults[0] == android.content.pm.PackageManager.PERMISSION_GRANTED){
mUpdateDialog.startUpdateApp();
}
}else if(requestCode == POST_NOTIFICATIONS_PERMISSION_CODE){
if(mUpdateDialog != null && grantResults.length > 0 && grantResults[0] == android.content.pm.PackageManager.PERMISSION_GRANTED){
mUpdateDialog.startUpdateApp();
}
}
}
@Override
public void onPermissionsGranted(int requestCode, @NonNull @NotNull List<String> perms) {
}
@Override
protected void onDestroy() {
super.onDestroy();
@@ -336,7 +354,7 @@ public class MainActivity extends BaseActivity<MainActivityLayoutBinding, MainPr
private void exitApp() {
if ((System.currentTimeMillis() - exitTime) > 2000) {
ToastUtil.showShort(getApplicationContext(), "再按一次退出");
ToastUtil.showShort(getApplicationContext(), getString(R.string.press_again_to_exit));
exitTime = System.currentTimeMillis();
} else {
//结束所有activity
@@ -358,24 +376,34 @@ public class MainActivity extends BaseActivity<MainActivityLayoutBinding, MainPr
if(bean == null){
return;
}
if(bean.getVersionCoercion().equals("0")){//不强制
if(!bean.isForceUpdate()){//不强制
isForceUpdate = false;
}else{
isForceUpdate = true;
}
//前期强制更新
// isForceUpdate = true;
if(bean.getVersionNumber() > versionCode){
if(bean.getVersionCode() > versionCode){
//App更新dialog
mUpdateDialog = new DialogAppUpdate(mContext,R.layout.dialog_app_update,isForceUpdate,bean);
mUpdateDialog = new DialogAppUpdate(mContext,R.layout.dialog_app_update_water,isForceUpdate,bean);
mUpdateDialog.show();
mUpdateDialog.setOnDialogListener(new DialogAppUpdate.DialogListener() {
@Override
public void callBackGetPermisson(String permission) {
if (!hasRecordPermission(permission)) {
if (Manifest.permission.POST_NOTIFICATIONS.equals(permission)) {
getPermissionRequst(permission,
"通知权限申请",
"渥田氏需要通知权限来显示应用下载进度",
POST_NOTIFICATIONS_PERMISSION_CODE);
return;
}
// 没有权限只在ACTION_DOWN时去申请
getPermissionRequst(permission,"文件存储权限申请",
"星语明灯需要您的授权,获取存储权限来更新您的应用",PICK_IMAGE_REQUEST_300);
getPermissionRequst(permission,
"文件存储权限申请",
"渥田氏需要您的授权,获取存储权限来更新您的应用",
WRITE_FILE_PERMISSON_CPDE);
}else{
@@ -415,14 +443,6 @@ public class MainActivity extends BaseActivity<MainActivityLayoutBinding, MainPr
@Override
public void onPermissionsGranted(int requestCode, @NonNull @NotNull List<String> perms) {
if (requestCode == ConstantUtil.WRITE_FILE_PERMISSON_CPDE) {
if(mUpdateDialog != null){
mUpdateDialog.startUpdateApp();
}
}
}
@Override
public void onPermissionsDenied(int requestCode, @NonNull @NotNull List<String> perms) {

View File

@@ -1,41 +1,32 @@
package com.ckkj.water.main.entity;
import com.google.gson.annotations.SerializedName;
import java.io.Serializable;
import lombok.Data;
import lombok.NoArgsConstructor;
@NoArgsConstructor
@Data
@NoArgsConstructor
public class CheckVersionEntity implements Serializable {
@SerializedName("versionNumber")
private int versionNumber;
@SerializedName("versionEnd")
private String versionEnd;
@SerializedName("versionCoercion")
private String versionCoercion;
@SerializedName("versionDescription")
private String versionDescription;
@SerializedName("versionName")
private String versionName;
@SerializedName("versionUrl")
private String versionUrl;
@SerializedName("versionHide1")
private String versionHide1;
@SerializedName("versionHide2")
private String versionHide2;
@SerializedName("versionHide3")
private String versionHide3;
@SerializedName("versionHide4")
private String versionHide4;
@SerializedName("versionHide5")
private Object versionHide5;
@SerializedName("versionHide6")
private Object versionHide6;
@SerializedName("paipanApiKey")
private String paipanApiKey;
/**
* platform : android
* currentVersion : 1.0.1
* latestVersion : 1.0.0
* versionCode : 1
* updateAvailable : true
* forceUpdate : false
* downloadUrl : null
* releaseNotes : null
*/
private String platform;
private String currentVersion;
private String latestVersion;
private int versionCode;
private boolean updateAvailable;
private boolean forceUpdate;
private String downloadUrl;
private String releaseNotes;
}

View File

@@ -5,7 +5,8 @@ import android.view.View;
import com.ckkj.water.R;
import com.ckkj.water.base.BaseActivity;
import com.ckkj.water.base.entity.MineUserInfoBean;
import com.ckkj.water.main.entity.CheckVersionEntity;
import com.ckkj.water.mine.entity.MineUserInfoBean;
import com.ckkj.water.databinding.AppThemeChangeLayoutBinding;
import com.ckkj.water.mine.mvp.MineContract;
import com.ckkj.water.mine.mvp.MineImpl;
@@ -57,6 +58,11 @@ public class AppThemActivity extends BaseActivity<AppThemeChangeLayoutBinding, M
public void onClick(View v){
switch (v.getId()){
case R.id.img_back:
finish();
break;
case R.id.linear_light:
case R.id.img_light:
switchTheme(ThemeManager.MODE_LIGHT);
@@ -102,4 +108,39 @@ public class AppThemActivity extends BaseActivity<AppThemeChangeLayoutBinding, M
public void getUserInfoSuccess(MineUserInfoBean bean) {
}
@Override
public void updateUserInfoSuccess(BaseBean bean) {
}
@Override
public void updateUserPasswordSuccess(BaseBean bean) {
}
@Override
public void logOutSuccess(BaseBean bean) {
}
@Override
public void uploadImageSuccess(MineUserInfoBean bean) {
}
@Override
public void getAppVersionSuccess(CheckVersionEntity bean) {
}
@Override
public void getAccountLogoffCodeSuccess(BaseBean bean) {
}
@Override
public void confirmAccountLogoffCodeSuccess(BaseBean bean) {
}
}

View File

@@ -5,7 +5,8 @@ import android.os.CountDownTimer;
import android.text.TextUtils;
import android.view.View;
import com.ckkj.water.base.entity.MineUserInfoBean;
import com.ckkj.water.main.entity.CheckVersionEntity;
import com.ckkj.water.mine.entity.MineUserInfoBean;
import com.gyf.immersionbar.ImmersionBar;
import com.ckkj.water.R;
import com.ckkj.water.base.BaseActivity;
@@ -14,7 +15,6 @@ import com.ckkj.water.mine.mvp.MineContract;
import com.ckkj.water.mine.mvp.MineImpl;
import com.ckkj.water.mine.mvp.MinePresenter;
import com.ckkj.water.network.BaseBean;
import com.ckkj.water.utils.manager.WaterUserInfoManager;
import com.ckkj.water.utils.number.PhoneNumberUtils;
import com.ckkj.water.utils.show.ToastUtil;
@@ -136,4 +136,39 @@ public class ChangePhoneActivity extends BaseActivity<ChangePhoneActivityBinding
public void getUserInfoSuccess(MineUserInfoBean bean) {
}
@Override
public void updateUserInfoSuccess(BaseBean bean) {
}
@Override
public void updateUserPasswordSuccess(BaseBean bean) {
}
@Override
public void logOutSuccess(BaseBean bean) {
}
@Override
public void uploadImageSuccess(MineUserInfoBean bean) {
}
@Override
public void getAppVersionSuccess(CheckVersionEntity bean) {
}
@Override
public void getAccountLogoffCodeSuccess(BaseBean bean) {
}
@Override
public void confirmAccountLogoffCodeSuccess(BaseBean bean) {
}
}

View File

@@ -1,34 +1,35 @@
package com.ckkj.water.mine;
import static android.view.View.INVISIBLE;
import static android.view.View.VISIBLE;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.View;
import com.bumptech.glide.Glide;
import com.ckkj.water.AppConfig;
import com.ckkj.water.ConstantUtil;
import com.ckkj.water.R;
import com.ckkj.water.base.BaseFragment;
import com.ckkj.water.base.entity.MineUserInfoBean;
import com.ckkj.water.databinding.MineFragmentBinding;
import com.ckkj.water.databinding.MineFragmentLayoutBinding;
import com.ckkj.water.main.entity.CheckVersionEntity;
import com.ckkj.water.mine.entity.MemberComboEntity;
import com.ckkj.water.mine.entity.MineUserInfoBean;
import com.ckkj.water.databinding.MineFragmentLayoutBinding;
import com.ckkj.water.login.LoginActivity;
import com.ckkj.water.mine.mvp.MineContract;
import com.ckkj.water.mine.mvp.MineImpl;
import com.ckkj.water.mine.mvp.MinePresenter;
import com.ckkj.water.network.BaseBean;
import com.ckkj.water.utils.dataUtil.SharePreUtil;
import com.ckkj.water.utils.manager.ActivityManager;
import com.ckkj.water.utils.manager.LanguageManager;
import com.ckkj.water.utils.manager.ThemeManager;
import com.ckkj.water.utils.manager.WaterUserInfoManager;
import com.ckkj.water.utils.show.ToastUtil;
import com.google.gson.Gson;
import com.gyf.immersionbar.ImmersionBar;
import com.lxj.xpopup.XPopup;
import com.lxj.xpopup.interfaces.OnSelectListener;
import java.util.List;
/**
* @author fengxiaoyang
* @date 2026/5/16
@@ -36,6 +37,7 @@ import java.util.List;
*/
public class MineCenterFragment extends BaseFragment<MineFragmentLayoutBinding, MinePresenter>
implements MineContract.MineView {
private MineUserInfoBean mUserBean;
@Override
public void initData(Bundle state) {
ImmersionBar.with(mContext)
@@ -44,6 +46,7 @@ public class MineCenterFragment extends BaseFragment<MineFragmentLayoutBinding,
.titleBar(viewBinding.rlTitle)
.init();
viewBinding.includedTitle.imgBack.setVisibility(INVISIBLE);
viewBinding.includedTitle.imgSetting.setVisibility(VISIBLE);
viewBinding.includedTitle.tvTitle.setText(getString(R.string.mine_center_title));
initListener();
}
@@ -57,10 +60,12 @@ public class MineCenterFragment extends BaseFragment<MineFragmentLayoutBinding,
}
private void initListener() {
setClick(viewBinding.imgAvatar);
setClick(viewBinding.linearInfo);
setClick(viewBinding.linearLanguage);
setClick(viewBinding.linearPsdManage);
setClick(viewBinding.linearTheme);
setClick(viewBinding.btnDelete);
setClick(viewBinding.includedTitle.imgSetting);
}
private void setClick(View view) {
@@ -69,8 +74,15 @@ public class MineCenterFragment extends BaseFragment<MineFragmentLayoutBinding,
public void onClick(View v){
switch (v.getId()){
case R.id.img_avatar:
goTo(mContext, MineInfomationActivity.class,null);
case R.id.img_setting:
goTo(mContext, SettingsActivity.class,null);
break;
case R.id.linear_info:
Bundle bundle = new Bundle();
bundle.putSerializable(ConstantUtil.USER_INFO_JSON_CONTENT,mUserBean);
goTo(mContext, MineInfomationActivity.class,bundle);
break;
case R.id.linear_theme:
@@ -83,14 +95,14 @@ public class MineCenterFragment extends BaseFragment<MineFragmentLayoutBinding,
.dismissOnBackPressed(true)
.dismissOnTouchOutside(true)
.asBottomList(
"选择语言",
new String[]{"中文", "English"},
new int[]{R.mipmap.ic_launcher, R.mipmap.ic_launcher},
0,
getString(R.string.change_language),
LanguageManager.getLanguageDisplayNames(mContext),
LanguageManager.getLanguageIcons(),
LanguageManager.getCurrentLanguageIndex(),
new OnSelectListener() {
@Override
public void onSelect(int position, String text) {
ToastUtil.showShort(mContext,text);
LanguageManager.switchLanguageByIndex(position, getActivity());
}
},
R.layout.select_language_layout,
@@ -101,6 +113,26 @@ public class MineCenterFragment extends BaseFragment<MineFragmentLayoutBinding,
case R.id.linear_psd_manage:
goTo(mContext, PsdManageActivity.class,null);
break;
case R.id.btn_delete:
showDialogtext(null,
false,
false,
getString(R.string.tip_text),
getString(R.string.logout_tips),
getString(R.string.cancel_text),
getString(R.string.confirm_text),
new OnDialogClick() {
@Override
public void onCancelClick() {
}
@Override
public void onConfirmClick() {
mPresenter.logout();
}
});
break;
}
}
@@ -114,9 +146,65 @@ public class MineCenterFragment extends BaseFragment<MineFragmentLayoutBinding,
String userInfoJson = gson.toJson(bean);
SharePreUtil.putString(ConstantUtil.SHARE_PRE_NAME,mContext,ConstantUtil.USER_INFO_JSON_CONTENT,userInfoJson);
WaterUserInfoManager.getInstance().setUserInfo(bean);
mUserBean = bean;
viewBinding.tvUserName.setText(bean.getUser().getNickName());
if(TextUtils.isEmpty(bean.getUser().getPhonenumber())){
viewBinding.tvUserAccount.setText(bean.getUser().getEmail());
}else{
viewBinding.tvUserAccount.setText(bean.getUser().getPhonenumber());
}
if(!TextUtils.isEmpty(bean.getUser().getAvatar())){
// 刷新头像显示
Glide.with(mContext)
.load(bean.getUser().getAvatar())
.error(mContext.getDrawable(R.mipmap.icon_mine_user_head_defaul))
.into(viewBinding.imgAvatar);
}
}
/**
* 退出登录
* @param bean
*/
@Override
public void logOutSuccess(BaseBean bean) {
WaterUserInfoManager.getInstance().clearUser(mContext);
ActivityManager.removeAllActivity();
goTo(mContext, LoginActivity.class,null);
}
@Override
public void uploadImageSuccess(MineUserInfoBean bean) {
}
@Override
public void getAppVersionSuccess(CheckVersionEntity bean) {
}
@Override
public void getAccountLogoffCodeSuccess(BaseBean bean) {
}
@Override
public void confirmAccountLogoffCodeSuccess(BaseBean bean) {
}
@Override
public void updateUserInfoSuccess(BaseBean bean) {
}
@Override
public void updateUserPasswordSuccess(BaseBean bean) {
}
@Override
public MinePresenter createPresenter() {
return new MinePresenter(new MineImpl());

View File

@@ -1,269 +0,0 @@
package com.ckkj.water.mine;
import static android.app.Activity.RESULT_OK;
import android.Manifest;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.View;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.alibaba.sdk.android.oss.ClientException;
import com.alibaba.sdk.android.oss.ServiceException;
import com.ckkj.water.base.entity.MineUserInfoBean;
import com.esafirm.imagepicker.features.ImagePicker;
import com.esafirm.imagepicker.model.Image;
import com.ckkj.water.AppConfig;
import com.ckkj.water.EventMessage;
import com.ckkj.water.R;
import com.ckkj.water.base.BaseFragment;
import com.ckkj.water.base.inter.UploadCallback;
import com.ckkj.water.databinding.MineFragmentBinding;
import com.ckkj.water.login.LoginActivity;
import com.ckkj.water.mine.mvp.MineContract;
import com.ckkj.water.mine.mvp.MineImpl;
import com.ckkj.water.mine.mvp.MinePresenter;
import com.ckkj.water.network.BaseBean;
import com.ckkj.water.utils.LubanCompressUtil;
import com.ckkj.water.utils.PreviewFileUtil;
import com.ckkj.water.utils.click.ClickUtil;
import com.ckkj.water.utils.dataUtil.FileUtil;
import com.ckkj.water.utils.manager.WaterUserInfoManager;
import com.ckkj.water.utils.oss.OssUploadHelper;
import com.ckkj.water.utils.show.ToastUtil;
import com.lxj.xpopup.XPopup;
import com.lxj.xpopup.interfaces.OnSelectListener;
import com.yalantis.ucrop.UCrop;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import de.greenrobot.event.EventBus;
import pub.devrel.easypermissions.EasyPermissions;
/**
* @author fengxiaoyang 新分支
* @date 2025/7/7
* @description TODO: 描述该类的作用
*/
public class MineFragment extends BaseFragment<MineFragmentBinding, MinePresenter>
implements MineContract.MineView {
@Override
public void initData(Bundle state) {
viewBinding.includedTitle.imgBack.setVisibility(View.GONE);
viewBinding.includedTitle.imgSetting.setVisibility(View.VISIBLE);
ClickUtil.addClickPart(viewBinding.includedTitle.imgSetting, 50);
ClickUtil.addClickPart(viewBinding.imgEdit, 50);
viewBinding.includedTitle.tvTitle.setText("个人中心");
}
@Override
protected void onResumeInitData() {
super.onResumeInitData();
if (AppConfig.USER_LOGIN) {
// mPresenter.getUserinfo();
} else {
viewBinding.tvDefaulBirthtime.setVisibility(View.VISIBLE);
viewBinding.tvDefaulStar.setVisibility(View.VISIBLE);
viewBinding.tvUserBirthTime.setVisibility(View.GONE);
viewBinding.tvUserStar.setVisibility(View.GONE);
}
}
@Override
public MinePresenter createPresenter() {
return new MinePresenter(new MineImpl());
}
public void onClick(View v) {
switch (v.getId()) {
case R.id.img_user_head:
if (!AppConfig.USER_LOGIN) {
goTo(mContext, LoginActivity.class, null);
return;
}
new XPopup.Builder(mContext).asBottomList("头像", new String[]{"上传头像", "查看大图"}, new OnSelectListener() {
@Override
public void onSelect(int position, String text) {
switch (position) {
case 0:
String readPermission = Manifest.permission.READ_EXTERNAL_STORAGE;
if (!hasRecordPermission(readPermission)) {
// 没有权限只在ACTION_DOWN时去申请
getPermissionRequst(readPermission, "相机、文件访问权限申请",
"星语明灯需要您的授权,获取文件访问权限来修改头像", REQUEST_CODE_100);
return;
} else {
imagePicker(1, REQUEST_CODE_100, MineFragment.this);
}
break;
case 1:
// String suffix = FileUtil.getFileSuffixWithQuestion(WaterUserInfoManager.getInstance().getUserInfo().getAvatar());
// PreviewFileUtil.previewFiles(mContext, suffix, WaterUserInfoManager.getInstance().getUserInfo().getAvatar());
break;
}
}
}).show();
break;
case R.id.img_setting:
goTo(mContext, SettingsActivity.class, null);
break;
case R.id.img_edit://编辑出生日期
if (!AppConfig.USER_LOGIN) {
goTo(mContext, LoginActivity.class, null);
return;
}
// 发送EventBus消息让MainActivity切换到FateFragment
EventBus.getDefault().post(new EventMessage(EventMessage.SWITCH_TO_FATE_FRAGMENT));
break;
case R.id.linear_tobe_vip:
case R.id.lienar_share_be_vip:
}
}
@Override
public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == RESULT_OK) {
switch (requestCode) {
case 100://头像
List<Image> images = ImagePicker.getImages(data);
Uri sourceUri = Uri.fromFile(new File(images.get(0).getPath()));
Uri destinationUri = Uri.fromFile(new File(mContext.getCacheDir(), "cropped_image.jpg"));
UCrop.of(sourceUri, destinationUri)
.withAspectRatio(1, 1) // 设置裁剪框比例1:1 为正方形
.withMaxResultSize(1000, 1000) // 设置裁剪后的最大图片尺寸
.start(requireContext(), this);
break;
case UCrop.REQUEST_CROP:
showLoadingDialog();
Uri resultUri = UCrop.getOutput(data);
String filePath = resultUri.getPath();
if (!TextUtils.isEmpty(filePath)) {
getCompressFile(new File(filePath));
}
break;
}
}
}
private void getCompressFile(File file) {
LubanCompressUtil.getInstance().getCompressFile(mContext, file, new LubanCompressUtil.CompressCallback() {
@Override
public void success(File file) {
if (file != null) {
if (file.exists()) {
long fileSizeInBytes = file.length(); // 获取文件大小(字节)
long fileSizeInMB = fileSizeInBytes / (1024 * 1024); // 转换为MB
String fileName = file.getName();
if (fileSizeInMB > 5) {
hideDialogLoading();
ToastUtil.showShort(mContext, "文件大小超出5M");
return;
}
if (!fileName.toLowerCase().endsWith(".png") &&
!fileName.toLowerCase().endsWith(".jpg") &&
!fileName.toLowerCase().endsWith(".jpeg")) {
ToastUtil.showShort(mContext, "文件格式不正确");
hideDialogLoading();
return;
}
List<String> filePath = new ArrayList<>();
filePath.add(file.getPath());
OssUploadHelper helper = new OssUploadHelper(mContext);
helper.upload(AppConfig.UPLOAD_TYPE_200, fileName, filePath, new UploadCallback() {
@Override
public void onSuccess(List<String> urls) {
mContext.runOnUiThread(new Runnable() {
@Override
public void run() {
if (!TextUtils.isEmpty(urls.get(0))) {
// mPresenter.updateUserAvatar(urls.get(0));
}
}
});
}
@Override
public void onFailure(ClientException clientException, ServiceException serviceException) {
}
});
} else {
ToastUtil.showShort(mContext, "文件不存在");
}
}
}
@Override
public void fail(String failMsg) {
}
});
}
@Override
public void onNetChange(int netModel) {
}
@Override
public void showError(String message) {
hideDialogLoading();
ToastUtil.showShort(mContext, message);
}
@Override
public void logOut(BaseBean bean) {
}
@Override
public void onPermissionsGranted(int requestCode, @NonNull List<String> perms) {
}
@Override
public void onPermissionsDenied(int requestCode, @NonNull List<String> perms) {
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this);
hidePermissionDialog();
if (requestCode == REQUEST_CODE_100) {
imagePicker(1, REQUEST_CODE_100, this);
}
}
@Override
public void getUserInfoSuccess(MineUserInfoBean bean) {
}
}

View File

@@ -3,15 +3,18 @@ package com.ckkj.water.mine;
import android.Manifest;
import android.content.Intent;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.View;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.bumptech.glide.Glide;
import com.ckkj.water.ConstantUtil;
import com.ckkj.water.R;
import com.ckkj.water.base.BaseActivity;
import com.ckkj.water.base.entity.MineUserInfoBean;
import com.ckkj.water.main.entity.CheckVersionEntity;
import com.ckkj.water.mine.entity.MineUserInfoBean;
import com.ckkj.water.databinding.MineInformationLayoutBinding;
import com.ckkj.water.mine.mvp.MineContract;
import com.ckkj.water.mine.mvp.MineImpl;
@@ -20,6 +23,8 @@ import com.ckkj.water.network.BaseBean;
import com.ckkj.water.utils.LubanCompressUtil;
import com.ckkj.water.utils.PreviewFileUtil;
import com.ckkj.water.utils.dataUtil.FileUtil;
import com.ckkj.water.utils.dataUtil.SharePreUtil;
import com.ckkj.water.utils.manager.ThemeManager;
import com.ckkj.water.utils.manager.WaterUserInfoManager;
import com.ckkj.water.utils.show.ToastUtil;
import com.esafirm.imagepicker.features.ImagePicker;
@@ -40,6 +45,7 @@ import pub.devrel.easypermissions.EasyPermissions;
*/
public class MineInfomationActivity extends BaseActivity<MineInformationLayoutBinding, MinePresenter>
implements MineContract.MineView, EasyPermissions.PermissionCallbacks{
private MineUserInfoBean mUserBean;
@Override
public MinePresenter createPresenter() {
return new MinePresenter(new MineImpl());
@@ -48,10 +54,26 @@ public class MineInfomationActivity extends BaseActivity<MineInformationLayoutBi
@Override
public void initData(Bundle savedInstanceState) {
super.initData(savedInstanceState);
Bundle bundle = getIntent().getExtras();
if(bundle != null){
mUserBean = (MineUserInfoBean) bundle.getSerializable(ConstantUtil.USER_INFO_JSON_CONTENT);
viewBinding.tvNicknameValue.setText(mUserBean.getUser().getNickName());
if(!TextUtils.isEmpty(mUserBean.getUser().getAvatar())){
// 刷新头像显示
Glide.with(mContext)
.load(mUserBean.getUser().getAvatar())
.error(mContext.getDrawable(R.mipmap.icon_mine_user_head_defaul))
.into(viewBinding.imgAvatar);
}
if(TextUtils.isEmpty(mUserBean.getUser().getEmail())){
viewBinding.tvBindPhoneValue.setText(mUserBean.getUser().getPhonenumber());
}else{
viewBinding.tvBindPhoneValue.setText(mUserBean.getUser().getEmail());
}
}
ImmersionBar.with(this)
.statusBarColor(R.color.white) // 设置状态栏颜色
.statusBarDarkFont(true) // 设置状态栏字体为黑色
.statusBarDarkFont(ThemeManager.isAppThemeLight(mContext)) // 白色状态栏图标
.navigationBarColor(R.color.mainBackgroundColor)
.titleBar(viewBinding.rlTitle)
.init();
viewBinding.includedTitle.tvTitle.setText(R.string.mine_infomation_title);
@@ -62,6 +84,7 @@ public class MineInfomationActivity extends BaseActivity<MineInformationLayoutBi
setClick(viewBinding.includedTitle.imgBack);
setClick(viewBinding.imgAvatar);
setClick(viewBinding.imgCamera);
setClick(viewBinding.rlNickname);
}
private void setClick(View view) {
@@ -76,7 +99,11 @@ public class MineInfomationActivity extends BaseActivity<MineInformationLayoutBi
case R.id.img_avatar:
case R.id.img_camera:
new XPopup.Builder(mContext).asBottomList("选择头像", new String[]{"上传头像", "查看大图"}, new OnSelectListener() {
new XPopup.Builder(mContext).asBottomList(
getString(R.string.avatar),
new String[]{
getString(R.string.upload_avatar),
getString(R.string.view_full_image)}, new OnSelectListener() {
@Override
public void onSelect(int position, String text) {
switch (position) {
@@ -84,21 +111,56 @@ public class MineInfomationActivity extends BaseActivity<MineInformationLayoutBi
String readPermission = Manifest.permission.READ_EXTERNAL_STORAGE;
if (!hasRecordPermission(readPermission)) {
// 没有权限只在ACTION_DOWN时去申请
getPermissionRequst(readPermission,"相册权限申请",
"智能浇水需要您的授权,获取相册修改头像",REQUEST_EVENT_CODE_10001);
getPermissionRequst(readPermission,
getString(R.string.request_camera_storage_permission),
getString(R.string.avatar_permission_tips),
REQUEST_EVENT_CODE_10001);
return;
}else{
imagePicker(1,PICK_IMAGE_REQUEST_100);
}
break;
case 1:
// String suffix = FileUtil.getFileSuffixWithQuestion(WaterUserInfoManager.getInstance().getUserInfo().getAvatar());
// PreviewFileUtil.previewFiles(mContext, suffix, WaterUserInfoManager.getInstance().getUserInfo().getAvatar());
String suffix = FileUtil.getFileSuffixWithQuestion(mUserBean.getUser().getAvatar());
PreviewFileUtil.previewFiles(mContext, suffix, mUserBean.getUser().getAvatar());
break;
}
}
}).show();
break;
case R.id.rl_nickname:
showEditDialog(
getString(R.string.edit_nickname),
getString(R.string.input_nickname),
mUserBean.getUser().getNickName(),
true,
getString(R.string.cancel_text),
getString(R.string.confirm_text),
INPUT_TYPE_NORMAL,
new OnDialogClick() {
@Override
public void onCancelClick() {
}
@Override
public void onConfirmClisk() {
}
@Override
public void onConfirmClisk(String content) {
showLoadingDialog();
mPresenter.updateUserInfo(content,null);
mUserBean.getUser().setNickName(content);
viewBinding.tvNicknameValue.setText(content);
}
@Override
public void onView1Click() {
}
});
break;
}
}
@@ -125,6 +187,69 @@ public class MineInfomationActivity extends BaseActivity<MineInformationLayoutBi
}
}
/**
* 获取个人信息成功
* @param bean
*/
@Override
public void updateUserInfoSuccess(BaseBean bean) {
hideDialogLoading();
}
@Override
public void updateUserPasswordSuccess(BaseBean bean) {
}
@Override
public void logOutSuccess(BaseBean bean) {
}
@Override
public void uploadImageSuccess(MineUserInfoBean bean) {
hideDialogLoading();
// 后端约定data 为上传后的头像访问URLString
String avatarUrl = bean.getUrl();
if (TextUtils.isEmpty(avatarUrl)) {
ToastUtil.showShort(mContext, getString(R.string.avatar_update_success));
return;
}
// 更新内存中的用户信息
if (mUserBean != null && mUserBean.getUser() != null) {
mUserBean.getUser().setAvatar(avatarUrl);
WaterUserInfoManager.getInstance().setUserInfo(mUserBean);
}
// 缓存头像地址到本地
SharePreUtil.putString(ConstantUtil.SHARE_PRE_NAME, mContext,
ConstantUtil.USER_INFO_AVATAR, avatarUrl);
// 刷新头像显示
Glide.with(mContext)
.load(avatarUrl)
.error(mContext.getDrawable(R.mipmap.icon_mine_user_head_defaul))
.into(viewBinding.imgAvatar);
ToastUtil.showShort(mContext, getString(R.string.avatar_update_success));
}
@Override
public void getAppVersionSuccess(CheckVersionEntity bean) {
}
@Override
public void getAccountLogoffCodeSuccess(BaseBean bean) {
}
@Override
public void confirmAccountLogoffCodeSuccess(BaseBean bean) {
}
private void getCompressFile(File file) {
LubanCompressUtil.getInstance().getCompressFile(mContext, file, new LubanCompressUtil.CompressCallback() {
@@ -137,26 +262,30 @@ public class MineInfomationActivity extends BaseActivity<MineInformationLayoutBi
String fileName = file.getName();
if (fileSizeInMB > 5) {
hideDialogLoading();
ToastUtil.showShort(mContext, "文件大小超出5M");
ToastUtil.showShort(mContext, getString(R.string.file_size_exceeds_5m));
return;
}
if (!fileName.toLowerCase().endsWith(".png") &&
!fileName.toLowerCase().endsWith(".jpg") &&
!fileName.toLowerCase().endsWith(".jpeg")) {
ToastUtil.showShort(mContext, "文件格式不正确");
ToastUtil.showShort(mContext, getString(R.string.invalid_file_format));
hideDialogLoading();
return;
}
hideDialogLoading();
ToastUtil.showShort(mContext,"头像修改成功");
// 上传图片
mPresenter.uploadImage(file);
Glide.with(mContext)
.load(file)
.error(mContext.getDrawable(R.mipmap.icon_mine_user_head_defaul))
.into(viewBinding.imgAvatar);
// hideDialogLoading();
// ToastUtil.showShort(mContext,getString(R.string.avatar_update_success));
//
// Glide.with(mContext)
// .load(file)
// .error(mContext.getDrawable(R.mipmap.icon_mine_user_head_defaul))
// .into(viewBinding.imgAvatar);
} else {
ToastUtil.showShort(mContext, "文件不存在");
ToastUtil.showShort(mContext, getString(R.string.file_not_exist));
}
}
}
@@ -176,7 +305,8 @@ public class MineInfomationActivity extends BaseActivity<MineInformationLayoutBi
@Override
public void showError(String message) {
hideDialogLoading();
ToastUtil.showShort(mContext,message);
}
@Override
@@ -210,4 +340,6 @@ public class MineInfomationActivity extends BaseActivity<MineInformationLayoutBi
public void getUserInfoSuccess(MineUserInfoBean bean) {
}
}

View File

@@ -5,13 +5,15 @@ import android.view.View;
import com.ckkj.water.R;
import com.ckkj.water.base.BaseActivity;
import com.ckkj.water.base.entity.MineUserInfoBean;
import com.ckkj.water.main.entity.CheckVersionEntity;
import com.ckkj.water.mine.entity.MineUserInfoBean;
import com.ckkj.water.databinding.PasswordManLayoutBinding;
import com.ckkj.water.login.ForgetPasswordActivity;
import com.ckkj.water.mine.mvp.MineContract;
import com.ckkj.water.mine.mvp.MineImpl;
import com.ckkj.water.mine.mvp.MinePresenter;
import com.ckkj.water.network.BaseBean;
import com.ckkj.water.utils.manager.ThemeManager;
import com.gyf.immersionbar.ImmersionBar;
/**
@@ -27,11 +29,11 @@ public class PsdManageActivity extends BaseActivity<PasswordManLayoutBinding, Mi
super.initData(savedInstanceState);
ImmersionBar.with(this)
.statusBarColor(R.color.white) // 设置状态栏颜色
.statusBarDarkFont(true) // 设置状态栏字体为黑色
.statusBarDarkFont(ThemeManager.isAppThemeLight(mContext)) // 白色状态栏图标
.navigationBarColor(R.color.mainBackgroundColor)
.titleBar(viewBinding.rlTitle)
.init();
viewBinding.includedTitle.tvTitle.setText(R.string.register_title);
viewBinding.includedTitle.tvTitle.setText(R.string.mine_psd_manager);
initListener();
}
@@ -85,4 +87,39 @@ public class PsdManageActivity extends BaseActivity<PasswordManLayoutBinding, Mi
public void getUserInfoSuccess(MineUserInfoBean bean) {
}
@Override
public void updateUserInfoSuccess(BaseBean bean) {
}
@Override
public void updateUserPasswordSuccess(BaseBean bean) {
}
@Override
public void logOutSuccess(BaseBean bean) {
}
@Override
public void uploadImageSuccess(MineUserInfoBean bean) {
}
@Override
public void getAppVersionSuccess(CheckVersionEntity bean) {
}
@Override
public void getAccountLogoffCodeSuccess(BaseBean bean) {
}
@Override
public void confirmAccountLogoffCodeSuccess(BaseBean bean) {
}
}

View File

@@ -1,17 +1,23 @@
package com.ckkj.water.mine;
import android.os.Bundle;
import android.text.InputType;
import android.text.TextUtils;
import android.text.method.PasswordTransformationMethod;
import android.view.View;
import android.widget.EditText;
import android.widget.ImageView;
import com.ckkj.water.R;
import com.ckkj.water.base.BaseActivity;
import com.ckkj.water.base.entity.MineUserInfoBean;
import com.ckkj.water.main.entity.CheckVersionEntity;
import com.ckkj.water.mine.entity.MineUserInfoBean;
import com.ckkj.water.databinding.ResetPsdLayoutBinding;
import com.ckkj.water.mine.mvp.MineContract;
import com.ckkj.water.mine.mvp.MineImpl;
import com.ckkj.water.mine.mvp.MinePresenter;
import com.ckkj.water.network.BaseBean;
import com.ckkj.water.utils.manager.ThemeManager;
import com.ckkj.water.utils.show.ToastUtil;
import com.gyf.immersionbar.ImmersionBar;
@@ -23,13 +29,17 @@ import com.gyf.immersionbar.ImmersionBar;
public class ResetPsdActivity extends BaseActivity<ResetPsdLayoutBinding, MinePresenter>
implements MineContract.MineView {
private boolean isOldPasswordVisible = false;
private boolean isNewPasswordVisible = false;
private boolean isConfirmPasswordVisible = false;
@Override
public void initData(Bundle savedInstanceState) {
super.initData(savedInstanceState);
ImmersionBar.with(this)
.statusBarColor(R.color.color_F9F9F9) // 设置状态栏颜色
.statusBarDarkFont(true) // 设置状态栏字体为黑色
.statusBarDarkFont(ThemeManager.isAppThemeLight(mContext)) // 白色状态栏图标
.navigationBarColor(R.color.color_gray_theme)
.titleBar(viewBinding.rlTitle)
.init();
viewBinding.includedTitle.tvTitle.setText(R.string.mine_psd_reset);
@@ -39,6 +49,9 @@ public class ResetPsdActivity extends BaseActivity<ResetPsdLayoutBinding, MinePr
private void initListener() {
setClick(viewBinding.includedTitle.imgBack);
setClick(viewBinding.tvCommit);
setClick(viewBinding.imgPsdShowHideOld);
setClick(viewBinding.imgPsdShowHideNew1);
setClick(viewBinding.imgPsdShowHideNew2);
}
private void setClick(View view) {
@@ -72,11 +85,85 @@ public class ResetPsdActivity extends BaseActivity<ResetPsdLayoutBinding, MinePr
ToastUtil.showShort(mContext,getString(R.string.hint_input_psd_not_match));
return;
}
ToastUtil.showShort(mContext,"接口触发");
showLoadingDialog();
mPresenter.updateUserPsdByOld(viewBinding.etCurrentPsd.getText().toString(),
viewBinding.etInputConfirmPsd.getText().toString());
break;
case R.id.img_psd_show_hide_old:
togglePasswordVisibility(viewBinding.etCurrentPsd, viewBinding.imgPsdShowHideOld,
isOldPasswordVisible);
isOldPasswordVisible = !isOldPasswordVisible;
break;
case R.id.img_psd_show_hide_new1:
togglePasswordVisibility(viewBinding.etNewPsd, viewBinding.imgPsdShowHideNew1,
isNewPasswordVisible);
isNewPasswordVisible = !isNewPasswordVisible;
break;
case R.id.img_psd_show_hide_new2:
togglePasswordVisibility(viewBinding.etInputConfirmPsd, viewBinding.imgPsdShowHideNew2,
isConfirmPasswordVisible);
isConfirmPasswordVisible = !isConfirmPasswordVisible;
break;
}
}
private void togglePasswordVisibility(EditText editText, ImageView imageView, boolean isVisible) {
if (editText == null || imageView == null) {
return;
}
if (isVisible) {
editText.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD);
editText.setTransformationMethod(PasswordTransformationMethod.getInstance());
imageView.setImageResource(R.mipmap.icon_psd_hide);
} else {
editText.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD);
editText.setTransformationMethod(null);
imageView.setImageResource(R.mipmap.icon_psd_show);
}
editText.setSelection(editText.getText().length());
}
/**
* 密码重置成功
* @param bean
*/
@Override
public void updateUserPasswordSuccess(BaseBean bean) {
hideDialogLoading();
ToastUtil.showShort(mContext,"密码重置成功");
finish();
}
@Override
public void logOutSuccess(BaseBean bean) {
}
@Override
public void uploadImageSuccess(MineUserInfoBean bean) {
}
@Override
public void getAppVersionSuccess(CheckVersionEntity bean) {
}
@Override
public void getAccountLogoffCodeSuccess(BaseBean bean) {
}
@Override
public void confirmAccountLogoffCodeSuccess(BaseBean bean) {
}
@Override
public MinePresenter createPresenter() {
return new MinePresenter(new MineImpl());
@@ -89,7 +176,8 @@ public class ResetPsdActivity extends BaseActivity<ResetPsdLayoutBinding, MinePr
@Override
public void showError(String message) {
hideDialogLoading();
ToastUtil.showShort(mContext,message);
}
@Override
@@ -101,4 +189,11 @@ public class ResetPsdActivity extends BaseActivity<ResetPsdLayoutBinding, MinePr
public void getUserInfoSuccess(MineUserInfoBean bean) {
}
@Override
public void updateUserInfoSuccess(BaseBean bean) {
}
}

View File

@@ -1,12 +1,22 @@
package com.ckkj.water.mine;
import static com.ckkj.water.ConstantUtil.POST_NOTIFICATIONS_PERMISSION_CODE;
import static com.ckkj.water.ConstantUtil.WRITE_FILE_PERMISSON_CPDE;
import android.Manifest;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.os.Handler;
import android.view.View;
import com.ckkj.water.base.entity.MineUserInfoBean;
import androidx.annotation.NonNull;
import com.ckkj.water.main.MainContract;
import com.ckkj.water.main.entity.CheckVersionEntity;
import com.ckkj.water.mine.entity.MineUserInfoBean;
import com.ckkj.water.utils.AppInfoUtil;
import com.ckkj.water.utils.manager.ThemeManager;
import com.gyf.immersionbar.ImmersionBar;
import com.ckkj.water.AppConfig;
import com.ckkj.water.EventMessage;
@@ -24,9 +34,13 @@ import com.ckkj.water.utils.manager.ActivityManager;
import com.ckkj.water.utils.manager.WaterUserInfoManager;
import com.ckkj.water.utils.show.ToastUtil;
import org.jetbrains.annotations.NotNull;
import java.io.File;
import java.util.List;
import de.greenrobot.event.EventBus;
import pub.devrel.easypermissions.EasyPermissions;
/**
* @author fengxiaoyang
@@ -35,23 +49,21 @@ import de.greenrobot.event.EventBus;
*/
public class SettingsActivity extends BaseActivity<ActivitySettingsLayoutBinding, MinePresenter>
implements MineContract.MineView {
implements MineContract.MineView, MainContract.MainView, EasyPermissions.PermissionCallbacks{
@Override
public void initData(Bundle savedInstanceState) {
super.initData(savedInstanceState);
ImmersionBar.with(this)
.statusBarColor(R.color.white)
.statusBarDarkFont(true)
.titleBar(viewBinding.rlTitle) // 替换为你的标题栏View
.keyboardEnable(true)
.navigationBarDarkIcon(true)
.statusBarDarkFont(ThemeManager.isAppThemeLight(mContext)) // 白色状态栏图标
.navigationBarColor(R.color.color_gray_theme)
.titleBar(viewBinding.rlTitle)
.init();
viewBinding.includeTitle.tvTitle.setText("设置");
viewBinding.includeTitle.tvTitle.setText(R.string.settings_title);
viewBinding.includeTitle.imgBack.setOnClickListener(c -> finish());
if(AppConfig.USER_LOGIN){
// viewBinding.tvUserPhone.setText(WaterUserInfoManager.getInstance().getUserInfo().getMobile());
viewBinding.tvLogOut.setVisibility(View.VISIBLE);
// viewBinding.tvLogOut.setVisibility(View.VISIBLE);
}
//获取本应用所占用的缓存
displayCacheSize();
@@ -62,12 +74,28 @@ public class SettingsActivity extends BaseActivity<ActivitySettingsLayoutBinding
PackageInfo packageInfo = packageManager.getPackageInfo(mContext.getPackageName(), 0);
// 获取版本名称
String versionName = packageInfo.versionName;
viewBinding.tvVersionName.setText("version " + versionName);
viewBinding.tvVersionName.setText(versionName);
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
initListener();
}
private void initListener() {
setClick(viewBinding.rlCheckVersion);
setClick(viewBinding.rlSetCache);
setClick(viewBinding.rlUserAgreement);
setClick(viewBinding.rlUserPrivacy);
setClick(viewBinding.rlLogOff);
}
private void setClick(View view) {
view.setOnClickListener(this::onClick);
}
@Override
public MinePresenter createPresenter() {
return new MinePresenter(new MineImpl());
@@ -81,16 +109,11 @@ public class SettingsActivity extends BaseActivity<ActivitySettingsLayoutBinding
public void onClick(View v) {
switch (v.getId()){
case R.id.rl_change_phone:
goTo(mContext, ChangePhoneActivity.class,null);
break;
case R.id.rl_check_version://版本检测
//版本检测更新
mPresenter.checkNewVersion();
break;
case R.id.rl_commit_service:
break;
case R.id.rl_set_cache:
showLoadingDialog();
@@ -99,29 +122,12 @@ public class SettingsActivity extends BaseActivity<ActivitySettingsLayoutBinding
@Override
public void run() {
hideDialogLoading();
ToastUtil.showShort(mContext,"缓存清除成功");
ToastUtil.showShort(mContext,getString(R.string.cache_cleared_success));
displayCacheSize();
}
},800);
break;
case R.id.tv_log_out:
showDialogtext(mContext.getResources().getDrawable(R.mipmap.img_location), false, false,true,
"提示", "确定要退出当前账号?",
"取消", "确定", new BaseFragment.OnDialogClick() {
@Override
public void onCancelClick() {
}
@Override
public void onConfirmClick() {
WaterUserInfoManager.getInstance().clearUser(mContext);
ActivityManager.removeAllActivity();
goTo(mContext, LoginActivity.class,null);
EventBus.getDefault().post(new EventMessage(EventMessage.USER_LOGIN_LOST));
}
});
break;
case R.id.rl_user_agreement://用户协议
Bundle bundle = new Bundle();
@@ -206,4 +212,129 @@ public class SettingsActivity extends BaseActivity<ActivitySettingsLayoutBinding
public void getUserInfoSuccess(MineUserInfoBean bean) {
}
@Override
public void updateUserInfoSuccess(BaseBean bean) {
}
@Override
public void updateUserPasswordSuccess(BaseBean bean) {
}
@Override
public void logOutSuccess(BaseBean bean) {
}
@Override
public void uploadImageSuccess(MineUserInfoBean bean) {
}
@Override
public void getAppVersionSuccess(CheckVersionEntity bean) {
int versionCode = (int) AppInfoUtil.getAppVersionCode(mContext);
if(bean == null){
return;
}
if(!bean.isForceUpdate()){//不强制
isForceUpdate = false;
}else{
isForceUpdate = true;
}
//前期强制更新
// isForceUpdate = true;
if(bean.getVersionCode() > versionCode){
//App更新dialog
mUpdateDialog = new DialogAppUpdate(mContext,R.layout.dialog_app_update_water,isForceUpdate,bean);
mUpdateDialog.show();
mUpdateDialog.setOnDialogListener(new DialogAppUpdate.DialogListener() {
@Override
public void callBackGetPermisson(String permission) {
if (!hasRecordPermission(permission)) {
if (Manifest.permission.POST_NOTIFICATIONS.equals(permission)) {
getPermissionRequst(permission,
getString(R.string.notification_permission_request),
getString(R.string.notification_permission_desc),
POST_NOTIFICATIONS_PERMISSION_CODE);
return;
}
// 没有权限只在ACTION_DOWN时去申请
getPermissionRequst(permission,
getString(R.string.storage_permission_request),
getString(R.string.storage_permission_desc),
WRITE_FILE_PERMISSON_CPDE);
}else{
}
}
@Override
public void downLoadFinish() {
runOnUiThread(new Runnable() {
@Override
public void run() {
ToastUtil.showShort(mContext,getString(R.string.download_complete_installing));
}
});
}
});
}else{
ToastUtil.showShort(mContext,"当前已是最新版本");
}
}
@Override
public void getAccountLogoffCodeSuccess(BaseBean bean) {
}
@Override
public void confirmAccountLogoffCodeSuccess(BaseBean bean) {
}
@Override
public void activationVipSuccess(BaseBean bean) {
}
@Override
public void getVersionCheck(CheckVersionEntity bean) {
}
@Override
public void getYunshiDataSuccess(BaseBean bean) {
}
@Override
public void onPermissionsGranted(int requestCode, @NonNull List<String> perms) {
}
@Override
public void onPermissionsDenied(int requestCode, @NonNull List<String> perms) {
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull @NotNull String[] permissions, @NonNull @NotNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this);
hidePermissionDialog();
if(requestCode == WRITE_FILE_PERMISSON_CPDE){
if(mUpdateDialog != null && grantResults.length > 0 && grantResults[0] == android.content.pm.PackageManager.PERMISSION_GRANTED){
mUpdateDialog.startUpdateApp();
}
}else if(requestCode == POST_NOTIFICATIONS_PERMISSION_CODE){
if(mUpdateDialog != null && grantResults.length > 0 && grantResults[0] == android.content.pm.PackageManager.PERMISSION_GRANTED){
mUpdateDialog.startUpdateApp();
}
}
}
}

View File

@@ -5,7 +5,12 @@ import android.os.CountDownTimer;
import android.text.TextUtils;
import android.view.View;
import com.ckkj.water.base.entity.MineUserInfoBean;
import com.ckkj.water.base.BaseFragment;
import com.ckkj.water.login.LoginActivity;
import com.ckkj.water.main.entity.CheckVersionEntity;
import com.ckkj.water.mine.entity.MineUserInfoBean;
import com.ckkj.water.utils.manager.ActivityManager;
import com.ckkj.water.utils.manager.WaterUserInfoManager;
import com.gyf.immersionbar.ImmersionBar;
import com.ckkj.water.AppConfig;
import com.ckkj.water.R;
@@ -15,8 +20,6 @@ import com.ckkj.water.mine.mvp.MineContract;
import com.ckkj.water.mine.mvp.MineImpl;
import com.ckkj.water.mine.mvp.MinePresenter;
import com.ckkj.water.network.BaseBean;
import com.ckkj.water.utils.manager.WaterUserInfoManager;
import com.ckkj.water.utils.number.PhoneNumberUtils;
import com.ckkj.water.utils.show.ToastUtil;
@@ -47,13 +50,26 @@ public class UserLogOffAccountActivity extends BaseActivity<UserLogOffActivityBi
.statusBarDarkFont(true) // 设置状态栏字体为黑色
.titleBar(viewBinding.rlTitle)
.init();
viewBinding.includeTitle.tvTitle.setText("注销账号");
viewBinding.includeTitle.tvTitle.setText(getString(R.string.delete_account));
viewBinding.includeTitle.imgBack.setOnClickListener(c -> finish());
if(AppConfig.USER_LOGIN){
// String phoneNum = WaterUserInfoManager.getInstance().getUserInfo().getMobile();
// if(!TextUtils.isEmpty(phoneNum)){
// viewBinding.tvUserPhone.setText(PhoneNumberUtils.hidePhoneNumber(phoneNum));
// }
String userAccount = (!TextUtils.isEmpty(WaterUserInfoManager.getInstance().getUserInfo().getUser().getPhonenumber()) ?
WaterUserInfoManager.getInstance().getUserInfo().getUser().getPhonenumber() :
WaterUserInfoManager.getInstance().getUserInfo().getUser().getEmail());
if(!TextUtils.isEmpty(userAccount)){
viewBinding.tvUserPhone.setText(userAccount);
}
}
initListener();
}
private void initListener() {
setClick(viewBinding.tvGetCode);
setClick(viewBinding.tvCommit);
}
private void setClick(View view) {
view.setOnClickListener(this::onClick);
}
@@ -65,26 +81,64 @@ public class UserLogOffAccountActivity extends BaseActivity<UserLogOffActivityBi
case R.id.tv_get_code:
showLoadingDialog();
mPresenter.getAccountLogoffCode();
break;
case R.id.tv_commit:
if(TextUtils.isEmpty(viewBinding.edVerCode.getText().toString().trim())){
ToastUtil.showShort(mContext,"请填写验证码");
ToastUtil.showShort(mContext, getString(R.string.login_error_code_empty));
return;
}
if(viewBinding.edVerCode.getText().toString().trim().length() < 6){
ToastUtil.showShort(mContext,"请填写6位验证码");
ToastUtil.showShort(mContext,getString(R.string.login_error_code_invalid));
return;
}
showDialogtext(null, false, false, true,
getString(R.string.tip_text),
getString(R.string.delete_account_tip),
getString(R.string.cancel_text),
getString(R.string.confirm_text),
new BaseFragment.OnDialogClick() {
@Override
public void onCancelClick() {
}
@Override
public void onConfirmClick() {
mPresenter.confirmAccountLogoff(viewBinding.edVerCode.getText().toString().trim());
}
});
break;
}
}
/**
* 获取账号注销验证码成功
* @param bean
*/
@Override
public void getAccountLogoffCodeSuccess(BaseBean bean) {
hideDialogLoading();
ToastUtil.showShort(mContext,getString(R.string.verification_code_sent));
}
/**
* 确认账号注销成功
* @param bean
*/
@Override
public void confirmAccountLogoffCodeSuccess(BaseBean bean) {
WaterUserInfoManager.getInstance().clearUser(mContext);
ActivityManager.removeAllActivity();
goTo(mContext, LoginActivity.class,null);
}
private CountDownTimer cdTimer = new CountDownTimer(60000, 1000) {
@Override
public void onTick(long millisUntilFinished) {
viewBinding.tvGetCode.setText("(" + millisUntilFinished / 1000 + ")秒后重发");
viewBinding.tvGetCode.setText("(" + millisUntilFinished / 1000 + ")" + getString(R.string.resend_after_seconds));
viewBinding.tvGetCode.setSelected(true);
viewBinding.tvGetCode.setClickable(false);
viewBinding.tvGetCode.setTextColor(mContext.getColor(R.color.color_c8c8c8));
@@ -92,7 +146,7 @@ public class UserLogOffAccountActivity extends BaseActivity<UserLogOffActivityBi
@Override
public void onFinish() {
viewBinding.tvGetCode.setText("重新发送");
viewBinding.tvGetCode.setText(getString(R.string.resend));
viewBinding.tvGetCode.setSelected(false);
viewBinding.tvGetCode.setClickable(true);
viewBinding.tvGetCode.setTextColor(mContext.getColor(R.color.color_zhu));
@@ -116,4 +170,31 @@ public class UserLogOffAccountActivity extends BaseActivity<UserLogOffActivityBi
public void getUserInfoSuccess(MineUserInfoBean bean) {
}
@Override
public void updateUserInfoSuccess(BaseBean bean) {
}
@Override
public void updateUserPasswordSuccess(BaseBean bean) {
}
@Override
public void logOutSuccess(BaseBean bean) {
}
@Override
public void uploadImageSuccess(MineUserInfoBean bean) {
}
@Override
public void getAppVersionSuccess(CheckVersionEntity bean) {
}
}

View File

@@ -0,0 +1,84 @@
package com.ckkj.water.mine.entity;
import java.io.Serializable;
import java.util.List;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @author fengxiaoyang
* @date 2025/7/28
* @description TODO: 描述该类的作用
*/
@NoArgsConstructor
@Data
public class MineUserInfoBean implements Serializable {
/**
* user : {"userId":"2056543507514097665","tenantId":"000000","deptId":null,"userName":null,"nickName":"给个回话","userType":"app_user","email":"","phonenumber":"133****6054","sex":"0","avatar":null,"password":"$2a$10$KsCb1Z1znyQgL7W.GoljuuVPctzZ7tS7obu8W2WkK5ydsejQOjRi2","status":"0","loginIp":"192.168.1.7","loginDate":"2026-05-21 08:44:20","remark":null,"createTime":"2026-05-19 09:12:36","deptName":null,"roles":[],"roleIds":null,"postIds":null,"roleId":null,"oldPassword":null}
* permissions : []
* roles : []
*/
private UserBean user;
private List<?> permissions;
private List<?> roles;
private String url;
@NoArgsConstructor
@Data
public static class UserBean implements Serializable{
/**
* userId : 2056543507514097665
* tenantId : 000000
* deptId : null
* userName : null
* nickName : 给个回话
* userType : app_user
* email :
* phonenumber : 133****6054
* sex : 0
* avatar : null
* password : $2a$10$KsCb1Z1znyQgL7W.GoljuuVPctzZ7tS7obu8W2WkK5ydsejQOjRi2
* status : 0
* loginIp : 192.168.1.7
* loginDate : 2026-05-21 08:44:20
* remark : null
* createTime : 2026-05-19 09:12:36
* deptName : null
* roles : []
* roleIds : null
* postIds : null
* roleId : null
* oldPassword : null
*/
private String userId;
private String tenantId;
private Object deptId;
private Object userName;
private String nickName;
private String userType;
private String email;
private String phonenumber;
private String sex;
private String avatar;
private String password;
private String status;
private String loginIp;
private String loginDate;
private Object remark;
private String createTime;
private Object deptName;
private Object roleIds;
private Object postIds;
private Object roleId;
private Object oldPassword;
private List<?> roles;
}
}

View File

@@ -1,18 +1,12 @@
package com.ckkj.water.mine.mvp;
import com.ckkj.water.base.IView;
import com.ckkj.water.base.entity.MineUserInfoBean;
import com.ckkj.water.login.mvp.LoginContract;
import com.ckkj.water.main.entity.CheckVersionEntity;
import com.ckkj.water.mine.entity.InviteeRecordEntity;
import com.ckkj.water.mine.entity.MemberComboEntity;
import com.ckkj.water.mine.entity.RecommendDataEntity;
import com.ckkj.water.mine.entity.RewardRecordEntity;
import com.ckkj.water.mine.entity.MineUserInfoBean;
import com.ckkj.water.network.BaseBean;
import org.json.JSONObject;
import java.util.List;
import java.util.Map;
/**
@@ -29,13 +23,34 @@ public class MineContract {
public interface DataModel{
//获取个人信息
void getUserInfo(Map<String,Object> map, CallBack callBack);
//更新个人信息
void updateUserInfo(JSONObject json, CallBack callBack);
//通过旧密码,修改新密码
void updateUserPwdByOld(JSONObject json, CallBack callBack);
//上传图片
void uploadImage(JSONObject json, CallBack callBack);
}
public interface MineView extends IView {
//获取个人信息
void getUserInfoSuccess(MineUserInfoBean bean);
//更新个人信息成功
void updateUserInfoSuccess(BaseBean bean);
//密码重设完成
void updateUserPasswordSuccess(BaseBean bean);
//退出登录
void logOutSuccess(BaseBean bean);
//上传图片成功
void uploadImageSuccess(MineUserInfoBean bean);
//获取新版本信息成功
void getAppVersionSuccess(CheckVersionEntity bean);
//获取注销账号验证码成功
void getAccountLogoffCodeSuccess(BaseBean bean);
//确认注销账号成功
void confirmAccountLogoffCodeSuccess(BaseBean bean);
}
public interface RecommendModel{

View File

@@ -1,14 +1,12 @@
package com.ckkj.water.mine.mvp;
import com.ckkj.water.base.entity.MineUserInfoBean;
import com.ckkj.water.login.mvp.LoginContract;
import com.ckkj.water.mine.entity.MemberComboEntity;
import com.ckkj.water.mine.entity.MineUserInfoBean;
import com.ckkj.water.network.BaseBean;
import com.ckkj.water.network.NetWorkManager;
import org.json.JSONObject;
import java.util.List;
import java.io.File;
import java.util.Map;
import io.reactivex.Observer;
@@ -16,6 +14,9 @@ import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.annotations.NonNull;
import io.reactivex.disposables.Disposable;
import io.reactivex.schedulers.Schedulers;
import okhttp3.MediaType;
import okhttp3.MultipartBody;
import okhttp3.RequestBody;
/**
* @author fengxiaoyang
@@ -59,4 +60,156 @@ public class MineImpl implements MineContract.DataModel {
}
});
}
/**
* 更新用户信息
* @param json
* @param callBack
*/
@Override
public void updateUserInfo(JSONObject json, MineContract.CallBack callBack) {
try {
NetWorkManager.getRequest().updateUserInfo(NetWorkManager.getToken(),NetWorkManager.toRequestBody(json))
.subscribeOn(Schedulers.io())
.unsubscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<BaseBean>() {
@Override
public void onSubscribe(@NonNull Disposable d) {
}
@Override
public void onNext(@NonNull BaseBean bean) {
if (bean.getCode() == 200) {
callBack.success(bean);
} else {
callBack.fail(bean.getMessage());
}
}
@Override
public void onError(@NonNull Throwable e) {
callBack.fail(e.getMessage());
}
@Override
public void onComplete() {
}
});
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 通过旧密码更新密码
* @param json
* @param callBack
*/
@Override
public void updateUserPwdByOld(JSONObject json, MineContract.CallBack callBack) {
try {
NetWorkManager.getRequest().updatePasswordByOld(NetWorkManager.getToken(),NetWorkManager.toRequestBody(json))
.subscribeOn(Schedulers.io())
.unsubscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<BaseBean>() {
@Override
public void onSubscribe(@NonNull Disposable d) {
}
@Override
public void onNext(@NonNull BaseBean bean) {
if (bean.getCode() == 200) {
callBack.success(bean);
} else {
callBack.fail(bean.getMessage());
}
}
@Override
public void onError(@NonNull Throwable e) {
callBack.fail(e.getMessage());
}
@Override
public void onComplete() {
}
});
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 上传图片
*
* @param json 预留参数,目前接口不需要,但保留扩展能力(例如上传类型/用户ID等
* @param callBack 上传结果回调
*/
@Override
public void uploadImage(JSONObject json, MineContract.CallBack callBack) {
File file = null;
if (json != null && json.has("file")) {
try {
String path = json.getString("file");
if (path != null && !path.isEmpty()) {
file = new File(path);
}
} catch (Exception e) {
e.printStackTrace();
}
}
if (file == null || !file.exists()) {
callBack.fail("文件不存在");
return;
}
// 推断 MIME 类型:根据后缀决定 image/jpeg 或 image/png其它统一用 image/jpeg
String fileName = file.getName().toLowerCase();
MediaType mediaType;
if (fileName.endsWith(".png")) {
mediaType = MediaType.parse("image/png");
} else if (fileName.endsWith(".jpg") || fileName.endsWith(".jpeg")) {
mediaType = MediaType.parse("image/jpeg");
} else {
mediaType = MediaType.parse("image/jpeg");
}
RequestBody requestBody = RequestBody.create(mediaType, file);
// 参数名固定为 "file",与后端约定一致
MultipartBody.Part part = MultipartBody.Part.createFormData("file", file.getName(), requestBody);
try {
NetWorkManager.getRequest().uploadImage(NetWorkManager.getToken(), part)
.subscribeOn(Schedulers.io())
.unsubscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<BaseBean<MineUserInfoBean>>() {
@Override
public void onSubscribe(@NonNull Disposable d) {
}
@Override
public void onNext(@NonNull BaseBean<MineUserInfoBean> bean) {
if (bean.getCode() == 200) {
callBack.success(bean.getData());
} else {
callBack.fail(bean.getMessage());
}
}
@Override
public void onError(@NonNull Throwable e) {
callBack.fail(e.getMessage());
}
@Override
public void onComplete() {
}
});
} catch (Exception e) {
e.printStackTrace();
callBack.fail(e.getMessage());
}
}
}

View File

@@ -2,14 +2,21 @@ package com.ckkj.water.mine.mvp;
import android.text.TextUtils;
import com.ckkj.water.ConstantUtil;
import com.ckkj.water.BuildConfig;
import com.ckkj.water.base.BasePresenter;
import com.ckkj.water.base.entity.MineUserInfoBean;
import com.ckkj.water.base.entity.UserInfoEntity;
import com.ckkj.water.utils.dataUtil.SharePreUtil;
import com.ckkj.water.utils.manager.WaterUserInfoManager;
import com.google.gson.Gson;
import com.ckkj.water.main.MainContract;
import com.ckkj.water.main.MainImpl;
import com.ckkj.water.main.MainPresenter;
import com.ckkj.water.main.entity.CheckVersionEntity;
import com.ckkj.water.mine.entity.MineUserInfoBean;
import com.ckkj.water.login.mvp.LoginContract;
import com.ckkj.water.login.mvp.LoginImpl;
import com.ckkj.water.network.BaseBean;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.File;
import java.util.HashMap;
import java.util.Map;
@@ -49,4 +56,194 @@ public class MinePresenter extends BasePresenter<MineContract.MineView> {
});
}
/**
* 修改用户信息
* @param nickName
* @param avatar
*/
public void updateUserInfo(String nickName,String avatar) {
try {
JSONObject json = new JSONObject();
if(!TextUtils.isEmpty(nickName)){
json.put("nickName", nickName);
}
if(!TextUtils.isEmpty(avatar)){
json.put("avatar", avatar);
}
impl.updateUserInfo(json, new MineContract.CallBack<BaseBean>() {
@Override
public void success(BaseBean bean) {
if(MinePresenter.this.getView() != null){
MinePresenter.this.getView().updateUserInfoSuccess(bean);
}
}
@Override
public void fail(String msg) {
if(MinePresenter.this.getView() != null){
MinePresenter.this.getView().showError(msg);
}
}
});
} catch (JSONException e) {
throw new RuntimeException(e);
}
}
/**
* 通过旧密码更新密码
* @param oldPsd
* @param newPsd
*/
public void updateUserPsdByOld(String oldPsd, String newPsd) {
try {
JSONObject json = new JSONObject();
json.put("oldPassword", oldPsd);
json.put("password", newPsd);
impl.updateUserPwdByOld(json, new MineContract.CallBack<BaseBean>() {
@Override
public void success(BaseBean bean) {
if(MinePresenter.this.getView() != null){
MinePresenter.this.getView().updateUserPasswordSuccess(bean);
}
}
@Override
public void fail(String msg) {
if(MinePresenter.this.getView() != null){
MinePresenter.this.getView().showError(msg);
}
}
});
} catch (JSONException e) {
throw new RuntimeException(e);
}
}
/**
* 退出登录
*/
public void logout() {
JSONObject json = new JSONObject();
new LoginImpl().logout(json, new LoginContract.CallBack<BaseBean>() {
@Override
public void success(BaseBean bean) {
if(MinePresenter.this.getView() != null){
MinePresenter.this.getView().logOutSuccess(bean);
}
}
@Override
public void fail(String msg) {
if(MinePresenter.this.getView() != null){
MinePresenter.this.getView().showError(msg);
}
}
});
}
/**
* 上传图片
* @param file 已压缩后的图片文件
*/
public void uploadImage(File file) {
try {
JSONObject json = new JSONObject();
json.put("file", file == null ? "" : file.getAbsolutePath());
impl.uploadImage(json, new MineContract.CallBack<MineUserInfoBean>() {
@Override
public void success(MineUserInfoBean bean) {
if (MinePresenter.this.getView() != null) {
MinePresenter.this.getView().uploadImageSuccess(bean);
updateUserInfo(null,bean.getUrl());
}
}
@Override
public void fail(String msg) {
if (MinePresenter.this.getView() != null) {
MinePresenter.this.getView().showError(msg);
}
}
});
} catch (JSONException e) {
e.printStackTrace();
if (getView() != null) {
getView().showError(e.getMessage());
}
}
}
public void checkNewVersion() {
Map<String,String> map = new HashMap<>();
map.put("platform","android");
map.put("currentVersion", BuildConfig.APP_VERSION_NAME);
new MainImpl().checkAppVersionCode(map, new MainContract.CallBack<CheckVersionEntity>() {
@Override
public void success(CheckVersionEntity bean) {
if( MinePresenter.this.getView() != null){
MinePresenter.this.getView().getAppVersionSuccess(bean);
}
}
@Override
public void fail(String msg) {
if( MinePresenter.this.getView() != null){
MinePresenter.this.getView().showError(msg);
}
}
});
}
/**
* 获取注销账号验证码
*/
public void getAccountLogoffCode() {
new LoginImpl().logoffAccountCode(null, new LoginContract.CallBack<BaseBean>() {
@Override
public void success(BaseBean bean) {
if(MinePresenter.this.getView() != null){
MinePresenter.this.getView().getAccountLogoffCodeSuccess(bean);
}
}
@Override
public void fail(String msg) {
if(MinePresenter.this.getView() != null){
MinePresenter.this.getView().showError(msg);
}
}
});
}
/**
* 确认注销账号
* @param verCode
*/
public void confirmAccountLogoff(String verCode) {
try {
Map<String,String> map = new HashMap<>();
map.put("code",verCode);
JSONObject json = new JSONObject();
json.put("code",verCode);
new LoginImpl().logoffAccount(json, new LoginContract.CallBack<BaseBean>() {
@Override
public void success(BaseBean bean) {
if(MinePresenter.this.getView() != null){
MinePresenter.this.getView().confirmAccountLogoffCodeSuccess(bean);
}
}
@Override
public void fail(String msg) {
if(MinePresenter.this.getView() != null){
MinePresenter.this.getView().showError(msg);
}
}
});
} catch (JSONException e) {
throw new RuntimeException(e);
}
}
}

View File

@@ -1,6 +1,7 @@
package com.ckkj.water.network;
import android.content.Context;
import android.text.TextUtils;
import android.util.Log;
import android.widget.Toast;
@@ -13,6 +14,7 @@ import com.ckkj.water.EventMessage;
import com.ckkj.water.MyApplication;
import com.ckkj.water.R;
import com.ckkj.water.utils.AppInfoUtil;
import com.ckkj.water.utils.manager.LanguageManager;
import org.json.JSONArray;
import org.json.JSONException;
@@ -82,6 +84,52 @@ public class NetWorkManager {
}
}
/**
* 响应拦截器:在 OkHttp 响应阶段直接捕获 HTTP 401/406/499 状态码,
* 同时打印请求 URL方便定位触发登录过期弹窗的具体接口。
*/
class ResponseInterceptor implements Interceptor {
@Override
public Response intercept(Chain chain) throws IOException {
okhttp3.Request request = chain.request();
String requestUrl = request.url().toString();
String requestMethod = request.method();
okhttp3.Response response = chain.proceed(request);
int httpCode = response.code();
if (httpCode == 401 || httpCode == 406 || httpCode == 499) {
Log.e("TEST", "触发401拦截 → HTTP状态码=" + httpCode
+ " | 请求方法=" + requestMethod
+ " | 请求URL=" + requestUrl);
}
try {
String responseBody = response.peekBody(1024 * 1024).string();
if (responseBody != null && !responseBody.trim().isEmpty()) {
JSONObject jsonObject = new JSONObject(responseBody);
String businessCode = jsonObject.optString("code");
if ("401".equals(businessCode)) {
Log.e("TEST", "业务401拦截 -> method=" + requestMethod
+ " | url=" + requestUrl
+ " | body=" + jsonObject.toString());
} else if ("406".equals(businessCode)) {
Log.e("TEST", "业务406拦截 -> method=" + requestMethod
+ " | url=" + requestUrl
+ " | body=" + jsonObject.toString());
} else if ("499".equals(businessCode)) {
Log.e("TEST", "业务499拦截 -> method=" + requestMethod
+ " | url=" + requestUrl
+ " | body=" + jsonObject.toString());
}
}
} catch (Exception e) {
Log.e("TEST", "响应体解析失败: " + e.getMessage());
}
return response;
}
}
/**
* 初始化必要对象和参数
*/
@@ -100,10 +148,14 @@ public class NetWorkManager {
Log.e("RetrofitLog", "retrofitBack=" + new Gson().toJson(jsonObject));
String s = jsonObject.getString("code");
if (s.equals("401")) {
Log.e("TEST", "触发401弹窗 → 业务code=401响应体=" + jsonObject.toString());
Log.e("TEST", "401发送堆栈:", new Throwable("NetWorkManager发送401堆栈"));
EventBus.getDefault().post(new EventMessage(EventMessage.USER_LOGIN_LOST));
} else if (s.equals("406")) {
}else if(s.equals("499")){
Log.e("TEST", "触发499弹窗 → 业务code=499响应体=" + jsonObject.toString());
Log.e("TEST", "499发送堆栈:", new Throwable("NetWorkManager发送499堆栈"));
EventBus.getDefault().post(new EventMessage(EventMessage.CODE_LOGIN_LOST));
// Activity activity = MyApplication.getCurrentActivity();
@@ -130,6 +182,7 @@ public class NetWorkManager {
// 初始化OkHttp
OkHttpClient client = new OkHttpClient.Builder()
.addInterceptor(loggingInterceptor) //添加网络拦截器
.addInterceptor(new ResponseInterceptor()) // HTTP状态码401/406/499拦截
.addInterceptor(new HeaderInterceptor()) //添加网络拦截器
.connectTimeout(120, TimeUnit.SECONDS)// 连接超时时间
.readTimeout(120, TimeUnit.SECONDS) //读取超时
@@ -336,9 +389,11 @@ public class NetWorkManager {
public static Map<String, String> getToken() {
Map<String, String> map = new HashMap<>();
try {
map.put("Authorization", "Bearer " + AppConfig.USER_TOKEN);
if(!TextUtils.isEmpty(AppConfig.USER_TOKEN)){
map.put("Authorization", "Bearer " + AppConfig.USER_TOKEN);
}
map.put("clientId", AppConfig.APP_CLIENT_ID);
// map.put("Authorization", "Bearer " + "eyJhbGciOiJIUzUxMiJ9.eyJ1c2VyX2lkIjoxOTI1NzYwMTgxMTMyNzI2MDIyLCJ1c2VyX2tleSI6IjY0YjVmMjRjLTIyM2ItNDRkZC1iMDJlLTI0ZTRiNzNmODgxZCIsInVzZXJuYW1lIjoiMTg2NDU5MDQzMDIifQ.PiIjBZlQ9UtOuotfhd5mZZO2e8SbMpbXU7VDvVeiWZIecsFDUd51Rae09EFxQ_MJmBUEvIdyysnyqYiBC2AEfw");
map.put("content-language", LanguageManager.getCurrentRequestLanguage());
} catch (Exception e) {
e.printStackTrace();
}

View File

@@ -2,23 +2,30 @@ package com.ckkj.water.network;
import com.ckkj.water.base.entity.MineUserInfoBean;
import com.ckkj.water.index.entity.IndexDeviceEntity;
import com.ckkj.water.mine.entity.MineUserInfoBean;
import com.ckkj.water.history.entity.WaterStatisticsEntity;
import com.ckkj.water.history.entity.WateringRecord;
import com.ckkj.water.index.entity.WaterDeviceEntity;
import com.ckkj.water.login.entity.LoginEntity;
import com.ckkj.water.main.entity.CheckVersionEntity;
import com.ckkj.water.plate.entity.BaziResultBean;
import com.ckkj.water.plate.entity.BaziSaveSuccessEntity;
import com.ckkj.water.plate.entity.PaipanHistoryEntity;
import com.ckkj.water.plan.entity.WaterPlanWeekEntity;
import java.util.List;
import java.util.Map;
import io.reactivex.Observable;
import okhttp3.MultipartBody;
import okhttp3.RequestBody;
import retrofit2.http.Body;
import retrofit2.http.DELETE;
import retrofit2.http.GET;
import retrofit2.http.HTTP;
import retrofit2.http.HeaderMap;
import retrofit2.http.Multipart;
import retrofit2.http.POST;
import retrofit2.http.PUT;
import retrofit2.http.Part;
import retrofit2.http.Path;
import retrofit2.http.QueryMap;
/**
@@ -30,46 +37,140 @@ public interface Request {
//发送验证码
@GET("resource/code")
Observable<BaseBean> sendPhoneCode(@HeaderMap Map<String, String> headMap,@QueryMap Map<String, Object> map);
//注销使用--发送验证码
@GET("resource/account/cancel/code")
Observable<BaseBean> logoffAccountCode(@HeaderMap Map<String, String> headMap);
//注销账户
@HTTP(method = "DELETE", path = "auth/account", hasBody = true)
Observable<BaseBean> confirmLogiffAccount(@HeaderMap Map<String,String> headMap,@Body RequestBody requestBody);
//注册
@POST("auth/register")
Observable<BaseBean> register(@Body RequestBody requestBody);
//退出登录
@POST("auth/logout")
Observable<BaseBean> logout(@Body RequestBody requestBody);
//登录
@POST("auth/login")
Observable<BaseBean<LoginEntity>> loginBySmsCode(@HeaderMap Map<String, String> headMap, @Body RequestBody requestBody);
//获取个人信息
@GET("app/v1/getUserInfo")
Observable<BaseBean<MineUserInfoBean>> getMineUserInfo(@HeaderMap Map<String, String> headMap, @QueryMap Map<String, Object> map);
//修改个人信息
@PUT("app/v1/updataUser")
Observable<BaseBean> updateUserInfo(@HeaderMap Map<String, String> headMap, @Body RequestBody requestBody);
//上传图片
@Multipart
@POST("app/v1/uploadImage")
Observable<BaseBean<MineUserInfoBean>> uploadImage(@HeaderMap Map<String, String> headMap,@Part MultipartBody.Part file);
//首页设备列表
@GET("app/v1/deviceList")
Observable<BaseBean<List<IndexDeviceEntity>>> getIndexDeviceList(@HeaderMap Map<String, String> headMap);
Observable<BaseBean<List<WaterDeviceEntity>>> getIndexDeviceList(@HeaderMap Map<String, String> headMap);
//查询设备编码,是否被绑定过,即当前设备状态
@POST("app/v1/bindDeviceStatus")
Observable<BaseBean<WaterDeviceEntity>> bindDeviceStatus(@HeaderMap Map<String, String> headMap, @Body RequestBody requestBody);
//添加设备
@POST("app/v1/addDevice")
Observable<BaseBean> addDevice(@HeaderMap Map<String, String> headMap, @Body RequestBody requestBody);
Observable<BaseBean<WaterDeviceEntity>> addDevice(@HeaderMap Map<String, String> headMap, @Body RequestBody requestBody);
//获取设备详细信息
@GET("app/v1/device/{deviceNo}")
Observable<BaseBean<WaterDeviceEntity>> getDeviceDetailInfo(@HeaderMap Map<String, String> headMap, @Path("deviceNo") String id);
//开启/关闭设备
@PUT("app/v1/switchDevice")
Observable<BaseBean<WaterPlanWeekEntity>> switchDevice(@HeaderMap Map<String, String> headMap, @Body RequestBody requestBody);
//查询设备工作开始时间和结束时间
@GET("app/v1/latestWaterLog")
Observable<BaseBean<WaterDeviceEntity>> queryDeviceWorkTime(@HeaderMap Map<String, String> headMap,@QueryMap Map<String, String> map);
//修改更新设备信息
@PUT("app/v1/updateDeviceInfo")
Observable<BaseBean> updateDeviceInfo(@HeaderMap Map<String, String> headMap, @Body RequestBody requestBody);
//通过旧密码修改密码
@PUT("app/v1/updataPassword")
Observable<BaseBean> updatePasswordByOld(@HeaderMap Map<String, String> headMap, @Body RequestBody requestBody);
//通过手机、邮箱验证码修改密码
@POST("app/v1/retrievePassword")
Observable<BaseBean> updatePasswordByVerifyCode(@HeaderMap Map<String, String> headMap, @Body RequestBody requestBody);
//查询排程列表
@GET("app/v1/schedulelist")
Observable<BaseBean<List<WaterPlanWeekEntity>>> scheduleList(@HeaderMap Map<String, String> headMap,@QueryMap Map<String, String> map);
//添加排程信息
@POST("app/v1/addschedule")
Observable<BaseBean<WaterPlanWeekEntity>> addSchedule(@HeaderMap Map<String, String> headMap, @Body RequestBody requestBody);
//编辑排程,更新
@PUT("app/v1/updataschedule")
Observable<BaseBean<WaterPlanWeekEntity>> updateSchedule(@HeaderMap Map<String, String> headMap, @Body RequestBody requestBody);
//查询排程可绑定设备列表
@GET("app/v1/scheduleDeviceList/{id}")
Observable<BaseBean<WaterDeviceEntity>> getPlanBindDeviceList(@HeaderMap Map<String, String> headMap, @Path("id") String id);
//查询排程详情
@GET("app/v1/schedule/{id}")
Observable<BaseBean<WaterPlanWeekEntity>> getPlanDetailInfo(@HeaderMap Map<String, String> headMap, @Path("id") String id);
//排程绑定设备
@POST("app/v1/addScheduleDevice")
Observable<BaseBean> planBindDevice(@HeaderMap Map<String, String> headMap, @Body RequestBody requestBody);
//更新排程状态
@PUT("app/v1/editScheduleStatus")
Observable<BaseBean<WaterPlanWeekEntity>> updateScheduleStatus(@HeaderMap Map<String, String> headMap, @Body RequestBody requestBody);
//删除排程
@DELETE("app/v1/deleteschedule/{ids}")
Observable<BaseBean> deletePlanById(@HeaderMap Map<String,String> headMap, @Path("ids") String id);
//删除设备
@DELETE("app/v1/deleteDevice/{deviceNo}")
Observable<BaseBean> unBindDevice(@HeaderMap Map<String,String> headMap, @Path("deviceNo") String id);
//排程解绑设备
@DELETE("app/v1/deleteScheduleDevice")
Observable<BaseBean> planUnBindDevice(@HeaderMap Map<String,String> headMap,@QueryMap Map<String, String> map);
//浇水历史记录
@GET("app/v1/waterLogList")
Observable<BaseBean<List<WateringRecord>>> waterLogList(@HeaderMap Map<String, String> headMap, @QueryMap Map<String, String> map);
//删除某一条历史记录
@DELETE("app/v1/waterLog/{id}")
Observable<BaseBean> deleteWaterLog(@HeaderMap Map<String,String> headMap, @Path("id") String id);
//浇水历史数据统计
@GET("app/v1/dataStatistics")
Observable<BaseBean<WaterStatisticsEntity>> getDataStatistics(@HeaderMap Map<String, String> headMap);
@POST("mobile/version?end=android")
Observable<BaseBean<CheckVersionEntity>> checkVersionCode(@HeaderMap Map<String, String> headMap, @Body RequestBody requestBody);
//版本检测更新
@GET("app/v1/checkVersion")
Observable<BaseBean<CheckVersionEntity>> checkVersionCode(@HeaderMap Map<String, String> headMap, @QueryMap Map<String, String> map);
@POST("mine/api/versionNum")
Observable<BaseBean<CheckVersionEntity>> getVersionCheck(@HeaderMap Map<String, String> headMap, @QueryMap Map<String, Object> map);
//保存排盘结果
@POST("mobile/paiPan")
Observable<BaseBean<BaziSaveSuccessEntity>> startPaipan(@HeaderMap Map<String, String> headMap, @Body RequestBody requestBody);
//AI解析排盘结果
@POST("mobile/paiPan/ai")
Observable<BaseBean> aiParesBaziResult(@HeaderMap Map<String, String> headMap, @Body RequestBody requestBody);
//开始排盘
@POST("https://api.yuanfenju.com/index.php/v1/Bazi/jingpan")
Observable<BaseYfjApiBean<BaziResultBean>> startPaipanByYfj(@HeaderMap Map<String, String> headMap, @QueryMap Map<String, Object> map);
//获取运势历史列表
@GET("mobile/paiPan/records")
Observable<BaseBean<PaipanHistoryEntity>> getPaipanHistoryList(@HeaderMap Map<String, String> headMap);
//删除历史记录
@POST("mobile/paiPan/record")
Observable<BaseBean> deletePaipanRecordById(@HeaderMap Map<String, String> headMap, @QueryMap Map<String, Object> map);

View File

@@ -1,17 +1,17 @@
package com.ckkj.water.permission;
import android.Manifest;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Bundle;
import android.view.View;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.core.content.ContextCompat;
import com.ckkj.water.ConstantUtil;
import com.ckkj.water.R;
import com.ckkj.water.base.BaseActivity;
import com.ckkj.water.base.BaseActivityNoP;
import com.ckkj.water.base.entity.MineUserInfoBean;
import com.ckkj.water.mine.entity.MineUserInfoBean;
import com.ckkj.water.databinding.PermissionLayoutBinding;
import com.ckkj.water.main.MainContract;
import com.ckkj.water.main.MainImpl;
@@ -32,6 +32,9 @@ import pub.devrel.easypermissions.EasyPermissions;
*/
public class PermissionActivity extends BaseActivity<PermissionLayoutBinding, MainPresenter>
implements MainContract.MainView, EasyPermissions.PermissionCallbacks {
private static final int REQUEST_BLUETOOTH_PERMISSION = 1002;
@Override
public MainPresenter createPresenter() {
return new MainPresenter(new MainImpl());
@@ -71,16 +74,52 @@ public class PermissionActivity extends BaseActivity<PermissionLayoutBinding, Ma
break;
case R.id.tv_commit:
String[] permission = {
Manifest.permission.ACCESS_FINE_LOCATION
};
boolean hasPermission = hasRecordPermission(permission);
if(!hasPermission){
getMorePermissionRequst(permission,"权限申请","智溉管家需要您的授权获取位置权限,用于添加设备",REQUEST_EVENT_CODE_10001);
}
// String[] permission = {
// Manifest.permission.ACCESS_FINE_LOCATION
// };
// boolean hasPermission = hasRecordPermission(permission);
// if(!hasPermission){
// getMorePermissionRequst(permission,"权限申请","智溉管家需要您的授权获取位置权限,用于添加设备",REQUEST_EVENT_CODE_10001);
// }
checkBluetoothPermissions();
break;
}
}
/**
* 检查蓝牙权限
*/
private boolean checkBluetoothPermissions() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
String[] readPermission = new String[]{
Manifest.permission.BLUETOOTH_SCAN,
Manifest.permission.BLUETOOTH_CONNECT,
Manifest.permission.ACCESS_FINE_LOCATION
};
if (!hasRecordPermission(readPermission)) {
// 没有权限只在ACTION_DOWN时去申请
getMorePermissionRequst(readPermission,
getString(R.string.bluetooth_permission_title),
getString(R.string.bluetooth_permission_desc),
REQUEST_EVENT_CODE_10003);
return false;
}
} else {
// Android 12 以下需要位置权限才能扫描蓝牙
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
!= PackageManager.PERMISSION_GRANTED) {
requestPermissions(new String[]{
Manifest.permission.ACCESS_FINE_LOCATION
}, REQUEST_EVENT_CODE_10003);
return false;
}
}
return true;
}
@Override
public void showError(String message) {
@@ -128,6 +167,9 @@ public class PermissionActivity extends BaseActivity<PermissionLayoutBinding, Ma
if (requestCode == REQUEST_EVENT_CODE_10001) {
ToastUtil.showShort(mContext,"权限获取成功");
finish();
}else if(requestCode == REQUEST_EVENT_CODE_10003){
ToastUtil.showShort(mContext,"蓝牙权限获取成功");
finish();
}
}

View File

@@ -1,40 +1,51 @@
package com.ckkj.water.plan;
import static android.view.View.GONE;
import static android.view.View.VISIBLE;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.View;
import androidx.fragment.app.Fragment;
import com.ckkj.water.R;
import com.ckkj.water.base.BaseActivity;
import com.ckkj.water.base.BaseFragment;
import com.ckkj.water.databinding.AddWaterPlanLayoutBinding;
import com.ckkj.water.index.entity.WaterDeviceEntity;
import com.ckkj.water.network.BaseBean;
import com.ckkj.water.plan.entity.WaterPlanWeekEntity;
import com.ckkj.water.plan.mvp.WaterPlanContract;
import com.ckkj.water.plan.mvp.WaterPlanImpl;
import com.ckkj.water.plan.mvp.WaterPlanPresenter;
import com.ckkj.water.plate.adapter.ViewPagerAdapter;
import com.ckkj.water.plan.adapter.ViewPagerAdapter;
import com.ckkj.water.utils.manager.ThemeManager;
import com.ckkj.water.utils.show.ToastUtil;
import com.gyf.immersionbar.ImmersionBar;
import java.util.ArrayList;
import java.util.List;
/**
* 添加浇水排程
* 添加/编辑浇水排程
*/
public class AddWaterPlanActivity extends BaseActivity<AddWaterPlanLayoutBinding, WaterPlanPresenter>
implements WaterPlanContract.WaterPlanView {
private List<Fragment> mFragmentList = new ArrayList<>();
private List<WaterPlanWeekEntity.DeviceEntity> mSelectedDevices = new ArrayList<>();
public List<WaterPlanWeekEntity.DeviceEntity> getSelectedDevices() {
return mSelectedDevices;
}
public void setSelectedDevices(List<WaterPlanWeekEntity.DeviceEntity> selectedDevices) {
this.mSelectedDevices = selectedDevices;
}
private boolean mIsEditMode = false;
private WaterPlanWeekEntity mEditEntity;
private WaterPlanWeekEntity mNewAddEntity;
// private List<WaterPlanWeekEntity.DeviceEntity> mSelectedDevices = new ArrayList<>();
//
// public List<WaterPlanWeekEntity.DeviceEntity> getSelectedDevices() {
// return mSelectedDevices;
// }
//
// public void setSelectedDevices(List<WaterPlanWeekEntity.DeviceEntity> selectedDevices) {
// this.mSelectedDevices = selectedDevices;
// }
@Override
public WaterPlanPresenter createPresenter() {
@@ -47,12 +58,26 @@ public class AddWaterPlanActivity extends BaseActivity<AddWaterPlanLayoutBinding
super.initData(savedInstanceState);
ImmersionBar.with(this)
.statusBarColor(R.color.color_F9F9F9) // 设置状态栏颜色
.statusBarDarkFont(true) // 设置状态栏字体为黑色
.statusBarDarkFont(ThemeManager.isAppThemeLight(mContext)) // 白色状态栏图标
.navigationBarColor(R.color.color_zhu)
.titleBar(viewBinding.rlTitle)
.init();
viewBinding.includedTitle.tvTitle.setText(R.string.add_water_plan_title);
Bundle bundle = getIntent().getExtras();
if (bundle != null) {
mIsEditMode = bundle.getBoolean("is_edit", false);
mEditEntity = (WaterPlanWeekEntity) bundle.getSerializable("plan_entity");
}
// 根据模式设置标题
if (mIsEditMode) {
viewBinding.includedTitle.tvTitle.setText(R.string.edit_water_plan_title);
viewBinding.tvBound.setVisibility(VISIBLE);
} else {
viewBinding.includedTitle.tvTitle.setText(R.string.add_water_plan_title);
viewBinding.tvBound.setVisibility(GONE);
}
mFragmentList.add(new WaterConfigFragment());
mFragmentList.add(new PlanBoundDeviceFragment());
mFragmentList.add(new BindDeviceFragment());
ViewPagerAdapter adapter = new ViewPagerAdapter(mContext, mFragmentList);
viewBinding.viewpage.setAdapter(adapter);
@@ -63,11 +88,23 @@ public class AddWaterPlanActivity extends BaseActivity<AddWaterPlanLayoutBinding
viewBinding.tvConfig.setSelected(true);
viewBinding.tvBind.setSelected(false);
initListener();
// 编辑模式下,延迟传递数据给 WaterConfigFragment等 viewBinding 初始化完成后调用
if (mIsEditMode && mEditEntity != null) {
viewBinding.viewpage.post(() -> {
WaterConfigFragment configFragment = (WaterConfigFragment) mFragmentList.get(0);
configFragment.setEditEntity(mEditEntity);
PlanBoundDeviceFragment boundDeviceFragment = (PlanBoundDeviceFragment) mFragmentList.get(1);
boundDeviceFragment.setEditEntity(mEditEntity);
});
}
}
private void initListener() {
setClick(viewBinding.includedTitle.imgBack);
setClick(viewBinding.tvConfig);
setClick(viewBinding.tvBound);
setClick(viewBinding.tvBind);
}
@@ -84,19 +121,119 @@ public class AddWaterPlanActivity extends BaseActivity<AddWaterPlanLayoutBinding
case R.id.tv_config:
viewBinding.tvConfig.setSelected(true);
viewBinding.tvBind.setSelected(false);
viewBinding.tvBound.setSelected(false);
viewBinding.viewpage.setCurrentItem(0);
break;
case R.id.tv_bind:
case R.id.tv_bound:
viewBinding.tvConfig.setSelected(false);
viewBinding.tvBind.setSelected(true);
viewBinding.tvBound.setSelected(true);
viewBinding.tvBind.setSelected(false);
viewBinding.viewpage.setCurrentItem(1);
// 传递编辑实体给 PlanBoundDeviceFragment
PlanBoundDeviceFragment boundDeviceFragment = (PlanBoundDeviceFragment) mFragmentList.get(1);
boundDeviceFragment.setEditEntity(mEditEntity);
break;
case R.id.tv_bind:
WaterConfigFragment configFragment = (WaterConfigFragment) mFragmentList.get(0);
// 检查是否有未保存的数据变更
if (configFragment.hasDataChanged()) {
showDialogtext(null, false, false, true,
getString(R.string.tip_text),
getString(R.string.data_changed_save_confirm),
getString(R.string.cancel_text),
getString(R.string.button_save),
new BaseFragment.OnDialogClick() {
@Override
public void onCancelClick() {
}
@Override
public void onConfirmClick() {
// 更新配置
configFragment.updateConfig();
}
});
return;
}
if (!configFragment.isConfigSubmitted()) {
// 校验新增排程的配置
if (!mIsEditMode) {
if (TextUtils.isEmpty(configFragment.getPlanName())) {
ToastUtil.showShort(mContext, getString(R.string.plan_name_text_empty_hint));
return;
}
if (!configFragment.hasTimeConfig()) {
ToastUtil.showShort(mContext, getString(R.string.schedule_select_at_least_one_day));
return;
}
}
showDialogtext(null, false, false, true,
getString(R.string.tip_text),
getString(R.string.save_schedule_before_bind_device),
getString(R.string.cancel_text),
getString(R.string.btn_continue), new BaseFragment.OnDialogClick() {
@Override
public void onCancelClick() {
}
@Override
public void onConfirmClick() {
configFragment.commitConfig();
}
});
return;
}
proceedToBindDevice();
break;
default:
break;
}
}
private void selectTabBind(WaterPlanWeekEntity entity) {
if (entity == null) {
entity = mIsEditMode ? mEditEntity : mNewAddEntity;
}
if (entity == null) {
ToastUtil.showShort(mContext, getString(R.string.please_save_schedule_first));
return;
}
viewBinding.tvConfig.setSelected(false);
viewBinding.tvBound.setSelected(false);
viewBinding.tvBind.setSelected(true);
viewBinding.viewpage.setCurrentItem(2);
// 传递排程数据给 BindDeviceFragment
BindDeviceFragment bindDeviceFragment = (BindDeviceFragment) mFragmentList.get(2);
bindDeviceFragment.setPlanEntity(entity);
}
/**
* 切换到绑定设备页面
*/
private void proceedToBindDevice() {
WaterConfigFragment configFragment = (WaterConfigFragment) mFragmentList.get(0);
WaterPlanWeekEntity entity = mIsEditMode ? mEditEntity : mNewAddEntity;
if (entity == null) {
entity = configFragment.getRemoteEntity();
}
selectTabBind(entity);
}
public void onConfigSaved(WaterPlanWeekEntity entity) {
mNewAddEntity = entity;
selectTabBind(entity);
}
@Override
public int getLayoutResId(Bundle savedInstanceState) {
return 0;
@@ -111,4 +248,50 @@ public class AddWaterPlanActivity extends BaseActivity<AddWaterPlanLayoutBinding
public void logOut(BaseBean bean) {
}
@Override
public void getWaterConfigListSuccess(List<WaterPlanWeekEntity> list,int total) {
}
@Override
public void saveConfigSuccess(WaterPlanWeekEntity entity) {
}
@Override
public void updateConfigSuccess(WaterPlanWeekEntity entity) {
}
@Override
public void updatePlanStatusSuccess(BaseBean bean, String status) {
}
@Override
public void getPlanDetailInfo(WaterPlanWeekEntity entity) {
}
@Override
public void getPlanBindDeviceList(WaterDeviceEntity bean) {
}
@Override
public void planBindDeviceSuccess(BaseBean bean) {
}
@Override
public void deletePlanSuccess(BaseBean bean) {
}
@Override
public void planUnbindDeviceSuccess(BaseBean bean, int position) {
}
}

View File

@@ -1,26 +1,25 @@
package com.ckkj.water.plan;
import android.os.Bundle;
import android.os.Handler;
import android.view.View;
import androidx.databinding.BindingAdapter;
import com.chad.library.adapter.base.BaseQuickAdapter;
import com.ckkj.water.R;
import com.ckkj.water.base.BaseFragment;
import com.ckkj.water.databinding.PlanBindDeviceLayoutBinding;
import com.ckkj.water.main.activity.MainActivity;
import com.ckkj.water.index.entity.WaterDeviceEntity;
import com.ckkj.water.network.BaseBean;
//import com.ckkj.water.plan.adapter.BindDeviceAdapter;
import com.ckkj.water.plan.adapter.BindDeviceAdapter;
import com.ckkj.water.plan.entity.WaterPlanWeekEntity;
import com.ckkj.water.plan.mvp.WaterPlanContract;
import com.ckkj.water.plan.mvp.WaterPlanImpl;
import com.ckkj.water.plan.mvp.WaterPlanPresenter;
import com.google.gson.Gson;
import com.ckkj.water.utils.show.ToastUtil;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
/**
* 排程关联设备
@@ -29,37 +28,145 @@ public class BindDeviceFragment extends BaseFragment<PlanBindDeviceLayoutBinding
implements WaterPlanContract.WaterPlanView {
private List<WaterPlanWeekEntity> weekList = new ArrayList<>();
private List<WaterDeviceEntity.DeviceListBean> mDeviceList = new ArrayList<>();
private WaterPlanWeekEntity mPlanEntity;
private BindDeviceAdapter mAdapter;
@Override
public void initData(Bundle state) {
String jsonContent = getString(R.string.plan_water_entity_json);
WaterPlanWeekEntity entity = new Gson().fromJson(jsonContent, WaterPlanWeekEntity.class);
weekList.add(entity);
mAdapter = new BindDeviceAdapter(mContext,R.layout.plan_bind_device_item,weekList.get(0).getDeviceList());
initListener();
mAdapter = new BindDeviceAdapter(mContext,R.layout.plan_bind_device_item,mDeviceList);
viewBinding.rvDevices.setAdapter(mAdapter);
mAdapter.setOnItemClickListener(new BaseQuickAdapter.OnItemClickListener() {
@Override
public void onItemClick(BaseQuickAdapter adapter, View view, int position) {
mAdapter.toggleSelection(position);
syncSelectedDevices();
if(mDeviceList.get(position).getCheckStatus().equals("0")){
mDeviceList.get(position).setCheckStatus("1");
}else{
mDeviceList.get(position).setCheckStatus("0");
}
}
});
if (mPlanEntity != null) {
mPresenter.getPlanBindDevices(mPlanEntity);
}
}
private void syncSelectedDevices() {
Set<Integer> selectedPositions = mAdapter.getSelectedPositions();
List<WaterPlanWeekEntity.DeviceEntity> selected = new ArrayList<>();
for (int pos : selectedPositions) {
if (pos >= 0 && pos < weekList.get(0).getDeviceList().size()) {
selected.add(weekList.get(0).getDeviceList().get(pos));
}
}
if (getActivity() instanceof AddWaterPlanActivity) {
((AddWaterPlanActivity) getActivity()).setSelectedDevices(selected);
private void initListener() {
setClick(viewBinding.tvCommit);
}
private void setClick(View view) {
view.setOnClickListener(this::onClick);
}
public void onClick(View v){
switch (v.getId()){
case R.id.tv_commit:
if (mPlanEntity == null) {
ToastUtil.showShort(mContext, "请先保存排程");
return;
}
boolean isSelected = false;
List<String> selected = new ArrayList<>();
for(WaterDeviceEntity.DeviceListBean bean : mDeviceList){
if(bean.getCheckStatus().equals("1")){
isSelected = true;
selected.add(bean.getDeviceNo());
}
}
if(!isSelected){
ToastUtil.showShort(mContext, getString(R.string.select_the_device_to_link));
return;
}
String selDevice = "";
for(String id : selected){
selDevice += id + ",";
}
selDevice = selDevice.substring(0,selDevice.length()-1);
//提交绑定
mPresenter.planBindWithDevices(mPlanEntity,selDevice);
break;
}
}
@Override
protected void onResumeInitData() {
super.onResumeInitData();
}
/**
* 设置排程实体,用于关联设备接口请求
* @param entity 排程实体
*/
public void setPlanEntity(WaterPlanWeekEntity entity) {
this.mPlanEntity = entity;
if (mPlanEntity != null) {
if(mPresenter != null){
mPresenter.getPlanBindDevices(mPlanEntity);
}
}
}
/**
* 查询到了可绑定的设备
* @param bean
*/
@Override
public void getPlanBindDeviceList(WaterDeviceEntity bean) {
hideDialogLoading();
if(mAdapter != null){
mDeviceList = bean.getDeviceList();
mAdapter.setNewData(mDeviceList);
if (mAdapter.getItemCount() != 0) {
viewBinding.relNoresult.setVisibility(View.GONE);
viewBinding.linearContent.setVisibility(View.VISIBLE);
} else {
viewBinding.relNoresult.setVisibility(View.VISIBLE);
viewBinding.linearContent.setVisibility(View.GONE);
}
}
}
@Override
public void planBindDeviceSuccess(BaseBean bean) {
hideDialogLoading();
ToastUtil.showShort(mContext, "绑定成功");
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
if (getActivity() instanceof AddWaterPlanActivity) {
((AddWaterPlanActivity) getActivity()).finish();
}
}
},800);
}
@Override
public void deletePlanSuccess(BaseBean bean) {
}
@Override
public void planUnbindDeviceSuccess(BaseBean bean, int position) {
}
// private void syncSelectedDevices() {
// Set<Integer> selectedPositions = mAdapter.getSelectedPositions();
// List<WaterPlanWeekEntity.DeviceEntity> selected = new ArrayList<>();
// for (int pos : selectedPositions) {
// if (pos >= 0 && pos < weekList.get(0).getDeviceList().size()) {
// selected.add(weekList.get(0).getDeviceList().get(pos));
// }
// }
// if (getActivity() instanceof AddWaterPlanActivity) {
// ((AddWaterPlanActivity) getActivity()).setSelectedDevices(selected);
// }
// }
@Override
public WaterPlanPresenter createPresenter() {
return new WaterPlanPresenter(new WaterPlanImpl());
@@ -79,4 +186,31 @@ public class BindDeviceFragment extends BaseFragment<PlanBindDeviceLayoutBinding
public void logOut(BaseBean bean) {
}
@Override
public void getWaterConfigListSuccess(List<WaterPlanWeekEntity> list,int total) {
}
@Override
public void saveConfigSuccess(WaterPlanWeekEntity entity) {
}
@Override
public void updateConfigSuccess(WaterPlanWeekEntity entity) {
}
@Override
public void updatePlanStatusSuccess(BaseBean bean, String status) {
}
@Override
public void getPlanDetailInfo(WaterPlanWeekEntity entity) {
}
}

View File

@@ -0,0 +1,196 @@
package com.ckkj.water.plan;
import android.os.Bundle;
import android.view.View;
import com.chad.library.adapter.base.BaseQuickAdapter;
import com.ckkj.water.R;
import com.ckkj.water.base.BaseFragment;
import com.ckkj.water.databinding.PlanBoundDeviceLayoutBinding;
import com.ckkj.water.index.entity.WaterDeviceEntity;
import com.ckkj.water.network.BaseBean;
import com.ckkj.water.plan.adapter.PlanBoundDeviceAdapter;
import com.ckkj.water.plan.entity.WaterPlanWeekEntity;
import com.ckkj.water.plan.mvp.WaterPlanContract;
import com.ckkj.water.plan.mvp.WaterPlanImpl;
import com.ckkj.water.plan.mvp.WaterPlanPresenter;
import com.ckkj.water.utils.show.ToastUtil;
import java.util.List;
/**
* @author fengxiaoyang
* @date 2026/5/29
* @description 已绑定的设备列表
*/
public class PlanBoundDeviceFragment extends BaseFragment<PlanBoundDeviceLayoutBinding, WaterPlanPresenter>
implements WaterPlanContract.WaterPlanView{
private WaterPlanWeekEntity mEditEntity;
private PlanBoundDeviceAdapter mAdapter;
@Override
public void initData(Bundle state) {
// 初始化适配器,如果有数据则设置
if (mEditEntity != null && mEditEntity.getDeviceNos() != null) {
mAdapter = new PlanBoundDeviceAdapter(mContext, R.layout.plan_bound_device_item, mEditEntity.getDeviceNos());
viewBinding.rvDevices.setAdapter(mAdapter);
// 根据数据状态显示/隐藏视图
if (mEditEntity.getDeviceNos().isEmpty()) {
viewBinding.linearContent.setVisibility(View.GONE);
viewBinding.relNoresult.setVisibility(View.VISIBLE);
} else {
viewBinding.linearContent.setVisibility(View.VISIBLE);
viewBinding.relNoresult.setVisibility(View.GONE);
}
} else {
// 无数据时显示空状态
viewBinding.linearContent.setVisibility(View.GONE);
viewBinding.relNoresult.setVisibility(View.VISIBLE);
}
if(mAdapter != null){
mAdapter.setOnItemChildClickListener(new BaseQuickAdapter.OnItemChildClickListener() {
@Override
public void onItemChildClick(BaseQuickAdapter adapter, View view, int position) {
switch (view.getId()){
case R.id.img_delete:
showDialogtext(null, false, false,
getString(R.string.tip_text),
getString(R.string.confirm_unbind_device),
getString(R.string.cancel_text),
getString(R.string.confirm_text),
new OnDialogClick() {
@Override
public void onCancelClick() {
}
@Override
public void onConfirmClick() {
showLoadingDialog();
mPresenter.planUnbindDevice(mEditEntity.getId(),
mEditEntity.getDeviceNos().get(position).getDeviceNo(),
position);
}
});
break;
}
}
});
}
}
public void setEditEntity(WaterPlanWeekEntity entity) {
this.mEditEntity = entity;
// 使用 getView().post() 确保视图已初始化完成
if (getView() != null) {
getView().post(() -> {
if (viewBinding != null) {
updateUI();
}
});
}
}
private void updateUI() {
if (viewBinding == null) {
return;
}
if (mEditEntity == null || mEditEntity.getDeviceNos() == null) {
viewBinding.linearContent.setVisibility(View.GONE);
viewBinding.relNoresult.setVisibility(View.VISIBLE);
return;
}
if (mEditEntity.getDeviceNos().isEmpty()) {
viewBinding.linearContent.setVisibility(View.GONE);
viewBinding.relNoresult.setVisibility(View.VISIBLE);
} else {
viewBinding.linearContent.setVisibility(View.VISIBLE);
viewBinding.relNoresult.setVisibility(View.GONE);
if (mAdapter != null) {
mAdapter.setNewData(mEditEntity.getDeviceNos());
}
}
}
public WaterPlanWeekEntity getEditEntity() {
return mEditEntity;
}
@Override
public WaterPlanPresenter createPresenter() {
return new WaterPlanPresenter(new WaterPlanImpl());
}
@Override
public void getWaterConfigListSuccess(List<WaterPlanWeekEntity> list, int total) {
}
@Override
public void saveConfigSuccess(WaterPlanWeekEntity entity) {
}
@Override
public void updateConfigSuccess(WaterPlanWeekEntity entity) {
}
@Override
public void updatePlanStatusSuccess(BaseBean bean, String status) {
}
@Override
public void getPlanDetailInfo(WaterPlanWeekEntity entity) {
}
@Override
public void getPlanBindDeviceList(WaterDeviceEntity bean) {
}
@Override
public void planBindDeviceSuccess(BaseBean bean) {
}
@Override
public void deletePlanSuccess(BaseBean bean) {
}
@Override
public void planUnbindDeviceSuccess(BaseBean bean, int position) {
hideDialogLoading();
ToastUtil.showShort(mContext, "解绑成功");
mAdapter.notifyItemRemoved(position);
mEditEntity.getDeviceNos().remove(position);
if (mAdapter.getItemCount() != 0) {
viewBinding.relNoresult.setVisibility(View.GONE);
viewBinding.linearContent.setVisibility(View.VISIBLE);
} else {
viewBinding.relNoresult.setVisibility(View.VISIBLE);
viewBinding.linearContent.setVisibility(View.GONE);
}
}
@Override
public void onNetChange(int netModel) {
}
@Override
public void showError(String message) {
}
@Override
public void logOut(BaseBean bean) {
}
}

View File

@@ -1,48 +1,99 @@
package com.ckkj.water.plan;
import android.os.Bundle;
import android.os.Handler;
import android.text.TextUtils;
import android.view.MotionEvent;
import android.view.View;
import com.ckkj.water.R;
import com.ckkj.water.base.BaseActivity;
import com.ckkj.water.base.BaseFragment;
import com.ckkj.water.databinding.WaterPlanDetailLayoutBinding;
import com.ckkj.water.index.entity.WaterDeviceEntity;
import com.ckkj.water.network.BaseBean;
//import com.ckkj.water.plan.adapter.PlanDetailDeviceAdapter;
//import com.ckkj.water.plan.adapter.PlanDetailTimeAdapter;
import com.ckkj.water.plan.adapter.PlanDetailDeviceAdapter;
import com.ckkj.water.plan.adapter.PlanDetailTimeAdapter;
import com.ckkj.water.plan.adapter.PlanWeekDaysAdapter;
import com.ckkj.water.plan.entity.WaterPlanWeekEntity;
import com.ckkj.water.plan.mvp.WaterPlanContract;
import com.ckkj.water.plan.mvp.WaterPlanImpl;
import com.ckkj.water.plan.mvp.WaterPlanPresenter;
import com.ckkj.water.utils.manager.ThemeManager;
import com.ckkj.water.utils.show.ToastUtil;
import com.ckkj.water.utils.time.ZYTimeUtils;
import com.google.gson.Gson;
import com.gyf.immersionbar.ImmersionBar;
import java.util.ArrayList;
import java.util.List;
/**
* 排程详情页面
*/
public class PlanDetailActivity extends BaseActivity<WaterPlanDetailLayoutBinding, WaterPlanPresenter>
implements WaterPlanContract.WaterPlanView {
//列表页面传的的,用于获取详情
private WaterPlanWeekEntity mPlanEntity;
//查询到的排程详情
private WaterPlanWeekEntity mDetailEntity;
private PlanWeekDaysAdapter mAdapter;
private PlanDetailDeviceAdapter deviceAdapter;
private List<WaterPlanWeekEntity.DetailsBean> mList = new ArrayList<>();
@Override
protected void onResume() {
super.onResume();
showLoadingDialog();
mPresenter.getPlanDetailInfo(mPlanEntity);
}
@Override
public void initData(Bundle savedInstanceState) {
super.initData(savedInstanceState);
Bundle bundle = getIntent().getExtras();
if(bundle != null){
mPlanEntity = (WaterPlanWeekEntity) bundle.getSerializable("plan_entity");
}
String jsonContent = getString(R.string.plan_water_entity_json);
WaterPlanWeekEntity entity = new Gson().fromJson(jsonContent, WaterPlanWeekEntity.class);
ImmersionBar.with(this)
.statusBarColor(R.color.color_F9F9F9) // 设置状态栏颜色
.statusBarDarkFont(true) // 设置状态栏字体为黑色
.statusBarDarkFont(ThemeManager.isAppThemeLight(mContext)) // 白色状态栏图标
.navigationBarColor(R.color.color_gray_theme)
.titleBar(viewBinding.rlTitle)
.init();
viewBinding.includedTitle.tvTitle.setText(R.string.plan_detail_title);
initListener();
PlanDetailTimeAdapter timeAdapter = new PlanDetailTimeAdapter(R.layout.plan_detail_time_item,entity.getWashCycleList());
viewBinding.rvPlanTime.setAdapter(timeAdapter);
PlanDetailDeviceAdapter deviceAdapter = new PlanDetailDeviceAdapter(R.layout.plan_detail_bind_device_item,entity.getDeviceList());
mAdapter = new PlanWeekDaysAdapter(R.layout.single_recycleview_item,mList);
viewBinding.rvPlanTime.setAdapter(mAdapter);
List<WaterDeviceEntity> deviceList = new ArrayList<>();
deviceAdapter = new PlanDetailDeviceAdapter(R.layout.plan_detail_bind_device_item,deviceList);
viewBinding.rvBindDevices.setAdapter(deviceAdapter);
}
private void initListener() {
setClick(viewBinding.includedTitle.imgBack);
setClick(viewBinding.btnEdit);
setClick(viewBinding.btnDelete);
setClick(viewBinding.switchButton);
// viewBinding.switchButton.setOnTouchListener(new View.OnTouchListener() {
// @Override
// public boolean onTouch(View v, MotionEvent event) {
// if (event.getAction() == MotionEvent.ACTION_DOWN) {
// if (viewBinding.switchButton.isChecked()) {
// // 当前是开启状态,下一步将是关闭 -> 屏蔽动画时长设为0
// 0
// } else {
// // 当前是关闭状态,下一步将是开启 -> 开启动画(恢复默认的 250ms 或你想要的时长)
// viewBinding.switchButton.setAnimationDuration(250);
// }
// }
// // 返回 false 以便将触摸事件继续传递给 SwitchButton 内部的点击/滑动逻辑
// return false;
// }
// });
}
private void setClick(View view) {
@@ -55,10 +106,171 @@ public class PlanDetailActivity extends BaseActivity<WaterPlanDetailLayoutBindin
finish();
break;
case R.id.btn_edit://编辑
if(mDetailEntity != null){
Bundle bundle = new Bundle();
bundle.putSerializable("plan_entity", mDetailEntity);
bundle.putBoolean("is_edit", true);
goTo(mContext, AddWaterPlanActivity.class,bundle);
}
break;
case R.id.btn_delete://删除
showDialogtext(null, false, false, true,
getString(R.string.tip_text),
getString(R.string.delete_plan_tip),
getString(R.string.cancel_text),
getString(R.string.confirm_text),
new BaseFragment.OnDialogClick() {
@Override
public void onCancelClick() {
}
@Override
public void onConfirmClick() {
mPresenter.deletePlan(mDetailEntity);
}
});
break;
case R.id.switch_button://切换状态
// 先恢复 Switch 到原始状态,避免点击时立即改变
viewBinding.switchButton.setChecked(mDetailEntity.getStatus().equals("1"));
if(mDetailEntity.getStatus().equals("1")){
showDialogtext(null, false, false, true,
getString(R.string.tip_text), getString(R.string.close_plan_dialog_tip),
getString(R.string.cancel_text), getString(R.string.confirm_text), new BaseFragment.OnDialogClick() {
@Override
public void onCancelClick() {
// 取消操作,恢复 Switch 状态
viewBinding.switchButton.setChecked(true);
}
@Override
public void onConfirmClick() {
// 确认关闭任务,调用接口后再更新 Switch
showLoadingDialog();
mPresenter.updatePlanStatus(mDetailEntity, "0");
}
});
}else{
// 开启任务,调用接口后再更新 Switch
mPresenter.updatePlanStatus(mDetailEntity, "1");
}
break;
}
}
/**
* 获取配成详情成功
* @param entity
*/
@Override
public void getPlanDetailInfo(WaterPlanWeekEntity entity) {
hideDialogLoading();
mDetailEntity = entity;
viewBinding.tvPlanName.setText(entity.getName());
if(entity.getStatus().equals("1")){
viewBinding.switchButton.setChecked(true);
viewBinding.tvPlanStatus.setText(getString(R.string.plan_on));
}else{
viewBinding.switchButton.setChecked(false);
viewBinding.tvPlanStatus.setText(getString(R.string.plan_off));
}
//针对周一 --- 周日的日期,只显示勾选的日期
List<WaterPlanWeekEntity.DetailsBean> list = new ArrayList<>();
for(WaterPlanWeekEntity.DetailsBean bean : entity.getDetails()){
if(bean.getStatus().equals("1")){
// 检查该日期是否有有效的时间配置
boolean hasValidTime = false;
if(bean.getTimeData() != null){
for(WaterPlanWeekEntity.TimeDataBean timeBean : bean.getTimeData()){
if(!TextUtils.isEmpty(timeBean.getStartTime())
&& timeBean.getDurationMin() != 0){
hasValidTime = true;
bean.setWeekName(ZYTimeUtils.getWeekName(bean.getWeekday() - 1,mContext));
break;
}
}
}
if(hasValidTime){
list.add(bean);
}
}
}
//日期显示
if(mAdapter != null){
mAdapter.setNewData(list);
}
//设备显示
if(deviceAdapter != null){
deviceAdapter.setNewData(entity.getDeviceNos());
if(deviceAdapter.getItemCount() == 0){
viewBinding.rvBindDevices.setVisibility(View.GONE);
viewBinding.tvNoDevice.setVisibility(View.VISIBLE);
}else{
viewBinding.rvBindDevices.setVisibility(View.VISIBLE);
viewBinding.tvNoDevice.setVisibility(View.GONE);
}
}
}
/**
* 删除排程成功
* @param bean
*/
@Override
public void deletePlanSuccess(BaseBean bean) {
hideDialogLoading();
ToastUtil.showShort(mContext,getString(R.string.delete_plan_success));
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
finish();
}
},500);
}
@Override
public void planUnbindDeviceSuccess(BaseBean bean, int position) {
}
/**
* 更新排程状态成功
*
* @param bean
* @param status
*/
@Override
public void updatePlanStatusSuccess(BaseBean bean, String status) {
hideDialogLoading();
mDetailEntity.setStatus(status);
if(status.equals("1")){
showCenterTipDialog(R.mipmap.icon_dialog_success,getString(R.string.task_started));
viewBinding.switchButton.setChecked(true);
viewBinding.tvPlanStatus.setText(getString(R.string.plan_on));
}else{
viewBinding.switchButton.setChecked(false);
viewBinding.tvPlanStatus.setText(getString(R.string.plan_off));
}
}
@Override
public void getPlanBindDeviceList(WaterDeviceEntity bean) {
}
@Override
public void planBindDeviceSuccess(BaseBean bean) {
}
@Override
public WaterPlanPresenter createPresenter() {
return new WaterPlanPresenter(new WaterPlanImpl());
@@ -71,11 +283,29 @@ public class PlanDetailActivity extends BaseActivity<WaterPlanDetailLayoutBindin
@Override
public void showError(String message) {
hideDialogLoading();
ToastUtil.showShort(mContext,message);
}
@Override
public void logOut(BaseBean bean) {
}
@Override
public void getWaterConfigListSuccess(List<WaterPlanWeekEntity> list,int total) {
}
@Override
public void saveConfigSuccess(WaterPlanWeekEntity entity) {
}
@Override
public void updateConfigSuccess(WaterPlanWeekEntity entity) {
}
}

View File

@@ -5,136 +5,682 @@ import android.text.Editable;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.view.View;
import android.view.ViewGroup;
import androidx.recyclerview.widget.RecyclerView;
import com.bigkoo.pickerview.builder.TimePickerBuilder;
import com.bigkoo.pickerview.listener.OnTimeSelectListener;
import com.bigkoo.pickerview.view.TimePickerView;
import com.chad.library.adapter.base.BaseQuickAdapter;
import com.ckkj.water.R;
import com.ckkj.water.base.BaseActivity;
import com.ckkj.water.base.BaseFragment;
import com.ckkj.water.databinding.WaterConfigFragmentLayoutBinding;
import com.ckkj.water.databinding.WaterConfigFragmentLayoutCopyBinding;
import com.ckkj.water.index.entity.WaterDeviceEntity;
import com.ckkj.water.network.BaseBean;
import com.ckkj.water.plan.adapter.WaterPlanWeekAdapter;
import com.ckkj.water.plan.adapter.WaterPlanTimeDataAdapter;
import com.ckkj.water.plan.adapter.WaterPlanWeekAdapter_copy;
import com.ckkj.water.plan.entity.WaterPlanWeekEntity;
import com.ckkj.water.plan.mvp.WaterPlanContract;
import com.ckkj.water.plan.mvp.WaterPlanImpl;
import com.ckkj.water.plan.mvp.WaterPlanPresenter;
import com.ckkj.water.utils.FastClickUtils;
import com.ckkj.water.utils.show.ToastUtil;
import com.ckkj.water.utils.time.ZYTimeUtils;
import com.google.gson.Gson;
import com.yanzhenjie.recyclerview.OnItemMenuClickListener;
import com.yanzhenjie.recyclerview.SwipeMenu;
import com.yanzhenjie.recyclerview.SwipeMenuBridge;
import com.yanzhenjie.recyclerview.SwipeMenuCreator;
import com.yanzhenjie.recyclerview.SwipeMenuItem;
import com.yanzhenjie.recyclerview.SwipeRecyclerView;
import com.yanzhenjie.recyclerview.widget.DefaultItemDecoration;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Locale;
public class WaterConfigFragment extends BaseFragment<WaterConfigFragmentLayoutBinding, WaterPlanPresenter>
public class WaterConfigFragment extends BaseFragment<WaterConfigFragmentLayoutCopyBinding, WaterPlanPresenter>
implements WaterPlanContract.WaterPlanView {
private List<WaterPlanWeekEntity> weekList = new ArrayList<>();
private WaterPlanWeekAdapter mWeekAdapter;
//本地新增排程时的实体
private WaterPlanWeekEntity mLocalEntity;
//新增之后返回的实体
private WaterPlanWeekEntity mRemoteEntity;
private List<WaterPlanWeekEntity.DetailsBean> weekList = new ArrayList<>();
private List<WaterPlanWeekEntity.TimeDataBean> timeList = new ArrayList<>();
private WaterPlanWeekAdapter_copy mWeekAdapter;
private WaterPlanTimeDataAdapter mTimeAdapter;
private RecyclerView.ItemDecoration itemDecoration;
private boolean isConfigSubmitted = false;
//当下是否编辑模式
private boolean mIsEditMode = false;
@Override
public void initData(Bundle state) {
String jsonContent = getString(R.string.plan_water_entity_json);
WaterPlanWeekEntity entity = new Gson().fromJson(jsonContent, WaterPlanWeekEntity.class);
weekList.add(entity);
mWeekAdapter = new WaterPlanWeekAdapter(mContext, R.layout.plan_period_item,weekList.get(0).getWashCycleList());
// 设置菜单创建器。
viewBinding.rvTimes.setSwipeMenuCreator(mSwipeMenuCreator);
viewBinding.rvTimes.setOnItemMenuClickListener(mItemMenuClickListener);
itemDecoration = new DefaultItemDecoration
(mContext.getColor(R.color.transparent),20,40);
viewBinding.rvTimes.addItemDecoration(itemDecoration);
List<WaterPlanWeekEntity.DetailsBean> list = new ArrayList<>();
for(int i = 0; i < 7; i++){
WaterPlanWeekEntity.DetailsBean bean = new WaterPlanWeekEntity.DetailsBean();
WaterPlanWeekEntity.TimeDataBean timeData = new WaterPlanWeekEntity.TimeDataBean();
List<WaterPlanWeekEntity.TimeDataBean> timeDataList = new ArrayList<>();
timeDataList.add(timeData);
bean.setTimeData(timeDataList);
bean.setWeekday(i + 1);
bean.setStatus("0");
bean.setWeekName(ZYTimeUtils.getWeekName(i,mContext));
bean.setTriggerType("0");
list.add(bean);
}
weekList = list;
//这里先处理新增,后面再处理编辑
mLocalEntity = new WaterPlanWeekEntity();
mLocalEntity.setStatus("1");
mLocalEntity.setDetails(weekList);
//顶部周一、周二。。。。。
mWeekAdapter = new WaterPlanWeekAdapter_copy(mContext, R.layout.plan_period_item,list);
viewBinding.rvWeek.setAdapter(mWeekAdapter);
//周期对应的 时间配置
List<WaterPlanWeekEntity.TimeDataBean> timeList = weekList.get(0).getTimeData();
mTimeAdapter = new WaterPlanTimeDataAdapter(mContext,R.layout.include_plan_time_item_layout,timeList);
viewBinding.rvTimes.setAdapter(mTimeAdapter);
viewBinding.switchButton.setChecked(weekList.get(0).getStatus().equals("1"));
initListener();
}
private void initListener() {
setClick(viewBinding.tvCommit);
setClick(viewBinding.tvSelectTime);
viewBinding.etPlanTime.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
@Override
public void afterTextChanged(Editable s) {
if(weekList != null){
String time = s.toString();
if(TextUtils.isEmpty(time)){
weekList.get(0).getWashCycleList().get(mWeekAdapter.getmPos()).setDuration("");
}else{
weekList.get(0).getWashCycleList().get(mWeekAdapter.getmPos()).setDuration(time);
}
}
}
});
setClick(viewBinding.imgAdd);
setClick(viewBinding.switchButton);
//头部 周一~周日
mWeekAdapter.setOnItemClickListener(new BaseQuickAdapter.OnItemClickListener() {
@Override
public void onItemClick(BaseQuickAdapter adapter, View view, int position) {
mWeekAdapter.setSelPos(position);
String planStartTime = weekList.get(0).getWashCycleList().get(position).getTime();
String planTime = weekList.get(0).getWashCycleList().get(position).getDuration();
List<WaterPlanWeekEntity.TimeDataBean> timeList = weekList.get(position).getTimeData();
mTimeAdapter.setNewData(timeList);
viewBinding.switchButton.setChecked(weekList.get(position).getStatus().equals("1"));
}
});
//周期对应的 时间配置
mTimeAdapter.setOnItemChildClickListener(new BaseQuickAdapter.OnItemChildClickListener() {
@Override
public void onItemChildClick(BaseQuickAdapter adapter, View view, int position) {
switch (view.getId()){
case R.id.tv_select_time:
selectStartTime(position);
break;
if(TextUtils.isEmpty(planStartTime)){
viewBinding.tvSelectTime.setHint(getString(R.string.select_water_time));
viewBinding.tvSelectTime.setText("");
}else{
viewBinding.tvSelectTime.setText(planStartTime);
case R.id.tv_plan_duration:
inputDuration(position);
break;
}
}
});
//输入框监听
viewBinding.editPlanName.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
if(TextUtils.isEmpty(planTime)){
viewBinding.etPlanTime.setHint(getString(R.string.input_water_plan_time));
viewBinding.etPlanTime.setText("");
}else{
viewBinding.etPlanTime.setText(planTime);
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {}
@Override
public void afterTextChanged(Editable s) {
String planName = "";
if(!TextUtils.isEmpty(s.toString())){
planName = s.toString();
}
mLocalEntity.setName(planName);
}
});
}
private void setClick(View view) {
view.setOnClickListener(this::onClick);
}
public void onClick(View v){
int selPos = mWeekAdapter.getmPos();
switch (v.getId()){
case R.id.tv_select_time:
boolean times[] = {false, false, false, true, true, false};
//时间选择器
TimePickerView pvTime = new TimePickerBuilder(mContext, new OnTimeSelectListener() {
@Override
public void onTimeSelect(Date date, View v) {
viewBinding.tvSelectTime.setText(ZYTimeUtils.getStrTimeData_H_M(date));
if(weekList != null){
String startTime = ZYTimeUtils.getStrTimeData_H_M(date).trim();
weekList.get(0).getWashCycleList().get(mWeekAdapter.getmPos()).setTime(startTime);
}
}
}).setType(times)
.setCancelColor(mContext.getColor(R.color.color_999999))
.setSubmitColor(mContext.getColor(R.color.color_zhu))
.setTextColorCenter(mContext.getColor(R.color.color_zhu))
.build();
pvTime.show();
case R.id.img_add:
isConfigSubmitted = false;
WaterPlanWeekEntity.TimeDataBean timeDataAdd = new WaterPlanWeekEntity.TimeDataBean();
weekList.get(selPos).getTimeData().add(timeDataAdd);
mTimeAdapter.notifyItemInserted(weekList.get(selPos).getTimeData().size() - 1);
break;
case R.id.switch_button:
if(weekList.get(selPos).getStatus().equals("0")){
weekList.get(selPos).setStatus("1");
viewBinding.switchButton.setChecked(true);
}else{
weekList.get(selPos).setStatus("0");
viewBinding.switchButton.setChecked(false);
}
break;
case R.id.tv_commit:
List<WaterPlanWeekEntity.DeviceEntity> list = getSelectedDevices();
if(list != null){
// 防止快速点击
if (!FastClickUtils.onclickTimes()) {
return;
}
// 如果已经保存过mRemoteEntity 不为空),则走更新逻辑;否则走新增逻辑
if (mRemoteEntity != null) {
updateConfig();
} else {
validateAndSave();
}
break;
}
}
private List<WaterPlanWeekEntity.DeviceEntity> getSelectedDevices() {
if (getActivity() instanceof AddWaterPlanActivity) {
return ((AddWaterPlanActivity) getActivity()).getSelectedDevices();
}
return new ArrayList<>();
public boolean isConfigSubmitted() {
return isConfigSubmitted;
}
/**
* 获取当前排程名称
* @return 排程名称
*/
public String getPlanName() {
if (mLocalEntity != null) {
return mLocalEntity.getName();
}
return "";
}
/**
* 检查是否至少配置了一天的时间
* @return true表示有时间配置false表示没有配置任何时间
*/
public boolean hasTimeConfig() {
for (WaterPlanWeekEntity.DetailsBean dayBean : weekList) {
List<WaterPlanWeekEntity.TimeDataBean> timeDataList = dayBean.getTimeData();
if (timeDataList != null && !timeDataList.isEmpty()) {
for (WaterPlanWeekEntity.TimeDataBean timeData : timeDataList) {
if (!TextUtils.isEmpty(timeData.getStartTime()) && timeData.getDurationMin() > 0) {
return true;
}
}
}
}
return false;
}
/**
* 校验并保存配置(供外部调用)
* @return true表示校验通过并已提交保存false表示校验失败
*/
public boolean commitConfig() {
return validateAndSave();
}
/**
* 更新配置(用于数据变更后调用)
* @return true表示校验通过并已提交更新false表示校验失败
*/
public boolean updateConfig() {
if (!validateConfig()) {
return false;
}
// 调用更新接口
if(mLocalEntity != null){
mPresenter.updateConfig(mLocalEntity);
}
return true;
}
/**
* 设置编辑模式的排程数据
* @param entity 从详情页传来的排程数据
*/
public void setEditEntity(WaterPlanWeekEntity entity) {
if (entity == null) {
return;
}
mIsEditMode = true;
// 深拷贝数据到 mConfigEntity用于本地编辑
mLocalEntity = cloneEntity(entity);
// 保存远程原始数据,用于后续变化检测
mRemoteEntity = entity;
isConfigSubmitted = true;
// 初始化 UI
viewBinding.editPlanName.setText(entity.getName());
// 更新周配置列表的显示,使用 mConfigEntity.getDetails() 保证数据一致
if (mLocalEntity.getDetails() != null) {
weekList = mLocalEntity.getDetails();
if(!weekList.isEmpty()){
viewBinding.switchButton.setChecked(weekList.get(0).getStatus().equals("1"));
mWeekAdapter.setNewData(mLocalEntity.getDetails());
mTimeAdapter.setNewData(weekList.get(mWeekAdapter.getmPos()).getTimeData());
}
}
}
/**
* 深拷贝 WaterPlanWeekEntity
*/
private WaterPlanWeekEntity cloneEntity(WaterPlanWeekEntity source) {
if (source == null) {
return null;
}
WaterPlanWeekEntity target = new WaterPlanWeekEntity();
target.setId(source.getId());
target.setName(source.getName());
target.setStatus(source.getStatus());
if (source.getDetails() != null) {
List<WaterPlanWeekEntity.DetailsBean> detailsList = new ArrayList<>();
for (WaterPlanWeekEntity.DetailsBean bean : source.getDetails()) {
WaterPlanWeekEntity.DetailsBean newBean = new WaterPlanWeekEntity.DetailsBean();
List<WaterPlanWeekEntity.TimeDataBean> timeDataList = new ArrayList<>();
for(WaterPlanWeekEntity.TimeDataBean timeDataBean : bean.getTimeData()){
WaterPlanWeekEntity.TimeDataBean newTimeDataBean = new WaterPlanWeekEntity.TimeDataBean();
newTimeDataBean.setStartTime(ZYTimeUtils.formatHHmm(timeDataBean.getStartTime()));
newTimeDataBean.setDurationMin(timeDataBean.getDurationMin());
timeDataList.add(newTimeDataBean);
}
newBean.setTimeData(timeDataList);
newBean.setId(bean.getId());
newBean.setWeekday(bean.getWeekday());
newBean.setWeekName(ZYTimeUtils.getWeekName(bean.getWeekday() - 1,mContext));
newBean.setStatus(bean.getStatus());
detailsList.add(newBean);
}
target.setDetails(detailsList);
}
return target;
}
/**
* 校验配置
* @return true表示校验通过false表示校验失败
*/
private boolean validateConfig() {
if(TextUtils.isEmpty(viewBinding.editPlanName.getText().toString())){
ToastUtil.showShort(mContext,getString(R.string.plan_name_text_empty_hint));
return false;
}
// 检查七天的所有时间配置是否全部为空
boolean allTimeEmpty = true;
for (WaterPlanWeekEntity.DetailsBean dayBean : weekList) {
List<WaterPlanWeekEntity.TimeDataBean> timeDataList = dayBean.getTimeData();
if (timeDataList != null && !timeDataList.isEmpty()) {
for (WaterPlanWeekEntity.TimeDataBean timeData : timeDataList) {
if (!TextUtils.isEmpty(timeData.getStartTime()) && timeData.getDurationMin() > 0) {
allTimeEmpty = false;
break;
}
}
}
if (!allTimeEmpty) break;
}
if (allTimeEmpty) {
ToastUtil.showShort(mContext, getString(R.string.schedule_select_at_least_one_day));
return false;
}
// 校验每一天内的时间是否有冲突
String conflictMsg = checkTimeConflict();
if (conflictMsg != null) {
ToastUtil.showShort(mContext, conflictMsg);
return false;
}
return true;
}
/**
* 校验配置并保存(新增)
* @return true表示校验通过并已提交保存false表示校验失败
*/
private boolean validateAndSave() {
if (!validateConfig()) {
return false;
}
if(mLocalEntity != null){
mPresenter.saveConfig(mLocalEntity);
return true;
}
return false;
}
/**
* 获取远程实体用于AddWaterPlanActivity比对
* @return mRemoteEntity
*/
public WaterPlanWeekEntity getRemoteEntity() {
return mRemoteEntity;
}
/**
* 获取本地实体用于AddWaterPlanActivity比对
* @return mLocalEntity
*/
public WaterPlanWeekEntity getLocalEntity() {
return mLocalEntity;
}
/**
* 检查本地数据是否与远程数据有变更
* @return true表示有变更false表示无变更
*/
public boolean hasDataChanged() {
if (mRemoteEntity == null || mLocalEntity == null) {
return false;
}
// 比对排程名称
String localName = mLocalEntity.getName();
String remoteName = mRemoteEntity.getName();
if (!TextUtils.isEmpty(localName) && !localName.equals(remoteName)) {
return true;
}
// 比对排程状态
String localStatus = mLocalEntity.getStatus();
String remoteStatus = mRemoteEntity.getStatus();
if (!TextUtils.isEmpty(localStatus) && !localStatus.equals(remoteStatus)) {
return true;
}
// 比对 details 列表
List<WaterPlanWeekEntity.DetailsBean> localDetails = mLocalEntity.getDetails();
List<WaterPlanWeekEntity.DetailsBean> remoteDetails = mRemoteEntity.getDetails();
if (localDetails == null && remoteDetails == null) {
return false;
}
if (localDetails == null || remoteDetails == null) {
return true;
}
if (localDetails.size() != remoteDetails.size()) {
return true;
}
// 逐个比对每个 DetailsBean
for (int i = 0; i < localDetails.size(); i++) {
WaterPlanWeekEntity.DetailsBean localDetail = localDetails.get(i);
WaterPlanWeekEntity.DetailsBean remoteDetail = remoteDetails.get(i);
// 比对 status
String localDetailStatus = localDetail.getStatus();
String remoteDetailStatus = remoteDetail.getStatus();
if (!TextUtils.isEmpty(localDetailStatus) && !localDetailStatus.equals(remoteDetailStatus)) {
return true;
}
// 比对 triggerType
String localTriggerType = localDetail.getTriggerType();
String remoteTriggerType = remoteDetail.getTriggerType();
if (!TextUtils.isEmpty(localTriggerType) && !localTriggerType.equals(remoteTriggerType)) {
return true;
}
// 比对 timeData 列表
List<WaterPlanWeekEntity.TimeDataBean> localTimeData = localDetail.getTimeData();
List<WaterPlanWeekEntity.TimeDataBean> remoteTimeData = remoteDetail.getTimeData();
if (localTimeData == null && remoteTimeData == null) {
continue;
}
if (localTimeData == null || remoteTimeData == null) {
return true;
}
if (localTimeData.size() != remoteTimeData.size()) {
return true;
}
// 逐个比对 TimeDataBean
for (int j = 0; j < localTimeData.size(); j++) {
WaterPlanWeekEntity.TimeDataBean localTime = localTimeData.get(j);
WaterPlanWeekEntity.TimeDataBean remoteTime = remoteTimeData.get(j);
// 比对 startTime
String localStartTime = localTime.getStartTime();
String remoteStartTime = remoteTime.getStartTime();
if (!TextUtils.isEmpty(localStartTime) && !localStartTime.equals(remoteStartTime)) {
return true;
}
// 比对 durationMin
if (localTime.getDurationMin() != remoteTime.getDurationMin()) {
return true;
}
}
}
return false;
}
/**
* 校验每一天内的时间配置是否有冲突
* @return null表示无冲突返回具体提示信息表示有冲突
*/
private String checkTimeConflict() {
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm", Locale.getDefault());
for (int dayIndex = 0; dayIndex < weekList.size(); dayIndex++) {
WaterPlanWeekEntity.DetailsBean dayBean = weekList.get(dayIndex);
List<WaterPlanWeekEntity.TimeDataBean> timeDataList = dayBean.getTimeData();
if (timeDataList == null || timeDataList.isEmpty()) {
continue;
}
// 收集该天所有有效的时间段(开始时间 + 结束时间)
List<long[]> periods = new ArrayList<>();
for (WaterPlanWeekEntity.TimeDataBean timeData : timeDataList) {
if (TextUtils.isEmpty(timeData.getStartTime()) || timeData.getDurationMin() <= 0) {
continue;
}
try {
Date startDate = sdf.parse(timeData.getStartTime());
long startMinutes = startDate.getHours() * 60 + startDate.getMinutes();
long endMinutes = startMinutes + timeData.getDurationMin();
periods.add(new long[]{startMinutes, endMinutes});
} catch (Exception e) {
e.printStackTrace();
}
}
// 检查是否有冲突
for (int i = 0; i < periods.size(); i++) {
for (int j = i + 1; j < periods.size(); j++) {
long[] p1 = periods.get(i);
long[] p2 = periods.get(j);
// 冲突条件:一个段的开始时间在另一个段的结束时间之前(即有重叠)
// 不冲突p1.end <= p2.start 或 p2.end <= p1.start
if (!(p1[1] <= p2[0] || p2[1] <= p1[0])) {
String dayName = dayBean.getWeekName();
return dayName + getString(R.string.schedule_time_conflict);
}
}
}
}
return null;
}
/**
* 选择开始时间
* @param position
*/
private void selectStartTime(int position) {
boolean times[] = {false, false, false, true, true, false};
Calendar selectedTime = Calendar.getInstance();
String startTime = weekList.get(mWeekAdapter.getmPos()).getTimeData().get(position).getStartTime();
if (!TextUtils.isEmpty(startTime)) {
try {
SimpleDateFormat timeFormat = new SimpleDateFormat("HH:mm", Locale.getDefault());
timeFormat.setLenient(false);
Date date = timeFormat.parse(startTime);
selectedTime.set(Calendar.HOUR_OF_DAY, date.getHours());
selectedTime.set(Calendar.MINUTE, date.getMinutes());
} catch (Exception ignored) {
}
}
//时间选择器
TimePickerView pvTime = new TimePickerBuilder(mContext, new OnTimeSelectListener() {
@Override
public void onTimeSelect(Date date, View v) {
//用于提交接口
weekList.get(mWeekAdapter.getmPos()).getTimeData().get(position).
setStartTime(ZYTimeUtils.getStrTimeData_H_M(date));
mTimeAdapter.notifyItemChanged(position);
}
}).setType(times)
.setCancelColor(mContext.getColor(R.color.color_999999))
.setSubmitColor(mContext.getColor(R.color.color_zhu))
.setTextColorCenter(mContext.getColor(R.color.color_zhu))
.setDate(selectedTime)
.build();
pvTime.show();
}
/**
* 输入浇水时间
* @param position
*/
private void inputDuration(int position) {
WaterPlanWeekEntity.TimeDataBean timeData = weekList.get(mWeekAdapter.getmPos()).getTimeData().get(position);
showEditDialog(getString(R.string.device_work_times_title),
getString(R.string.input_water_plan_time),
timeData.getDurationMin() == 0 ? "" : timeData.getDurationMin() + "",
true,
getString(R.string.cancel_text),
getString(R.string.confirm_text),
BaseFragment.INPUT_TYPE_NUMBER,
new BaseActivity.OnDialogClick() {
@Override
public void onCancelClick() {}
@Override
public void onConfirmClisk() {}
@Override
public void onConfirmClisk(String content) {
if(TextUtils.isEmpty(content)){
ToastUtil.showShort(mContext, getString(R.string.input_water_plan_time_error));
return;
}
if (Integer.parseInt(content) <= 0) {
ToastUtil.showShort(mContext, getString(R.string.input_water_plan_time_error));
return;
}
timeData.setDurationMin(Integer.parseInt(content));
mTimeAdapter.notifyItemChanged(position);
}
@Override
public void onView1Click() {
}
});
}
/**
* 侧滑相关
*/
// 创建菜单:
SwipeMenuCreator mSwipeMenuCreator = new SwipeMenuCreator() {
@Override
public void onCreateMenu(SwipeMenu leftMenu, SwipeMenu rightMenu, int position) {
SwipeMenuItem deleteItem = new SwipeMenuItem(mContext);
deleteItem.setBackground(mContext.getResources().getDrawable(R.drawable.shape_item_delete_bg));
deleteItem.setText(getString(R.string.button_delete));
deleteItem.setTextColor(mContext.getResources().getColor(R.color.white));
deleteItem.setHeight(ViewGroup.LayoutParams.MATCH_PARENT);
deleteItem.setWidth((int) mContext.getResources().getDimension(R.dimen.dp_90));
// 各种文字和图标属性设置。
rightMenu.addMenuItem(deleteItem); // 在Item右侧添加一个菜单。
}
};
// 菜单点击监听。
OnItemMenuClickListener mItemMenuClickListener = new OnItemMenuClickListener() {
@Override
public void onItemClick(SwipeMenuBridge menuBridge, int position) {
// 先关闭菜单
menuBridge.closeMenu();
// 左/右菜单
int direction = menuBridge.getDirection();
// 点击的是第几个菜单
int menuPosition = menuBridge.getPosition();
// 只处理右侧菜单
if (direction == SwipeRecyclerView.RIGHT_DIRECTION) {
if (menuPosition == 0) {
weekList.get(mWeekAdapter.getmPos()).getTimeData().remove(position);
if(mTimeAdapter != null){
mTimeAdapter.notifyItemRemoved(position);
}
}
}
}
};
/**
* 新增
* @param entity
*/
@Override
public void saveConfigSuccess(WaterPlanWeekEntity entity) {
ToastUtil.showShort(mContext, getString(R.string.schedule_add_success));
isConfigSubmitted = true;
// 把接口返回的 ID 设置到 mConfigEntity便于后续更新操作
mLocalEntity.setId(entity.getId());
// 把 details 中每个 bean 的 id 也设置到 mConfigEntity便于后续更新操作
if (entity.getDetails() != null && mLocalEntity.getDetails() != null) {
for (int i = 0; i < entity.getDetails().size() && i < mLocalEntity.getDetails().size(); i++) {
mLocalEntity.getDetails().get(i).setId(entity.getDetails().get(i).getId());
mLocalEntity.getDetails().get(i).setStatus(entity.getDetails().get(i).getStatus());
}
}
//接口请求之后返回的数据,方便后面做对比
mRemoteEntity = entity;
if (getActivity() instanceof AddWaterPlanActivity) {
((AddWaterPlanActivity) getActivity()).onConfigSaved(entity);
}
}
/**
* 更新
* @param entity
*/
@Override
public void updateConfigSuccess(WaterPlanWeekEntity entity) {
ToastUtil.showShort(mContext, getString(R.string.schedule_update_success));
mRemoteEntity = entity;
}
// private List<WaterPlanWeekEntity.DeviceEntity> getSelectedDevices() {
// if (getActivity() instanceof AddWaterPlanActivity) {
// return ((AddWaterPlanActivity) getActivity()).getSelectedDevices();
// }
// return new ArrayList<>();
// }
@Override
public WaterPlanPresenter createPresenter() {
return new WaterPlanPresenter(new WaterPlanImpl());
@@ -154,4 +700,41 @@ public class WaterConfigFragment extends BaseFragment<WaterConfigFragmentLayoutB
public void logOut(BaseBean bean) {
}
@Override
public void getWaterConfigListSuccess(List<WaterPlanWeekEntity> list, int total) {
}
@Override
public void updatePlanStatusSuccess(BaseBean bean, String status) {
}
@Override
public void getPlanDetailInfo(WaterPlanWeekEntity entity) {
}
@Override
public void getPlanBindDeviceList(WaterDeviceEntity bean) {
}
@Override
public void planBindDeviceSuccess(BaseBean bean) {
}
@Override
public void deletePlanSuccess(BaseBean bean) {
}
@Override
public void planUnbindDeviceSuccess(BaseBean bean, int position) {
}
}

View File

@@ -1,38 +1,49 @@
package com.ckkj.water.plan;
import static android.view.View.INVISIBLE;
import static android.view.View.VISIBLE;
import android.content.Context;
import android.os.Bundle;
import android.view.View;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodManager;
import com.chad.library.adapter.base.BaseQuickAdapter;
import com.ckkj.water.R;
import com.ckkj.water.base.BaseFragment;
import com.ckkj.water.custom.view.CustomRefreshHeader;
import com.ckkj.water.databinding.WaterPlanFragmentBinding;
import com.ckkj.water.main.activity.MainActivity;
import com.ckkj.water.index.entity.WaterDeviceEntity;
import com.ckkj.water.network.BaseBean;
//import com.ckkj.water.plan.adapter.WaterPlanListAdapter;
import com.ckkj.water.plan.adapter.WaterPlanListAdapter;
import com.ckkj.water.plan.entity.WaterPlanWeekEntity;
import com.ckkj.water.plan.mvp.WaterPlanContract;
import com.ckkj.water.plan.mvp.WaterPlanImpl;
import com.ckkj.water.plan.mvp.WaterPlanPresenter;
import com.ckkj.water.utils.manager.ThemeManager;
import com.ckkj.water.utils.show.ToastUtil;
import com.google.gson.Gson;
import com.gyf.immersionbar.ImmersionBar;
import com.scwang.smart.refresh.footer.ClassicsFooter;
import com.scwang.smart.refresh.layout.api.RefreshHeader;
import java.util.ArrayList;
import java.util.List;
public class WaterPlanFragment extends BaseFragment<WaterPlanFragmentBinding, WaterPlanPresenter>
implements WaterPlanContract.WaterPlanView {
private List<WaterPlanWeekEntity.DeviceEntity> mDevList = new ArrayList<>();
private List<WaterPlanWeekEntity> mPlanList = new ArrayList<>();
private WaterPlanListAdapter mAdapter;
private int mCurrentPage = 1;
private String mSearchOption = "";
@Override
public void initData(Bundle state) {
String jsonContent = getString(R.string.plan_water_entity_json);
WaterPlanWeekEntity entity = new Gson().fromJson(jsonContent, WaterPlanWeekEntity.class);
mDevList = entity.getDeviceList();
// mDevList = entity.getDeviceList();
ImmersionBar.with(mContext)
.statusBarColor(R.color.mainBackgroundColor)
@@ -41,21 +52,67 @@ public class WaterPlanFragment extends BaseFragment<WaterPlanFragmentBinding, Wa
.init();
viewBinding.includedTitle.imgBack.setVisibility(INVISIBLE);
viewBinding.includedTitle.tvTitle.setText(getString(R.string.plan_title));
viewBinding.includedNoresult.tvAddPlan.setVisibility(VISIBLE);
initListener();
mAdapter = new WaterPlanListAdapter(mContext,R.layout.water_plan_list_item,mDevList);
mAdapter = new WaterPlanListAdapter(mContext,R.layout.water_plan_list_item,mPlanList);
viewBinding.rvPlans.setAdapter(mAdapter);
mAdapter.setOnItemClickListener(new BaseQuickAdapter.OnItemClickListener() {
@Override
public void onItemClick(BaseQuickAdapter adapter, View view, int position) {
goTo(mContext, PlanDetailActivity.class,null);
Bundle bundle = new Bundle();
bundle.putSerializable("plan_entity",mPlanList.get(position));
goTo(mContext, PlanDetailActivity.class,bundle);
}
});
RefreshHeader header = new CustomRefreshHeader(mContext);
viewBinding.refresh.setRefreshHeader(header);
viewBinding.refresh.setRefreshFooter(new ClassicsFooter(mContext));
viewBinding.refresh.setOnRefreshListener(layout -> {
mSearchOption = "";
mCurrentPage = 1;
viewBinding.refresh.setNoMoreData(false);
mPresenter.getWaterPlanList(mCurrentPage,mSearchOption);
viewBinding.etInputPlanName.setText("");
});
viewBinding.refresh.setOnLoadMoreListener(layout -> {
mCurrentPage++;
mPresenter.getWaterPlanList(mCurrentPage,mSearchOption);
});
//文本输入搜索排程
viewBinding.etInputPlanName.setOnEditorActionListener((v, actionId, event) -> {
if (actionId == EditorInfo.IME_ACTION_SEARCH) {
// 隐藏键盘
InputMethodManager imm = (InputMethodManager) v.getContext()
.getSystemService(Context.INPUT_METHOD_SERVICE);
if (imm != null) {
imm.hideSoftInputFromWindow(v.getWindowToken(), 0);
}
// 清除焦点(可选,避免键盘再次弹出)
v.clearFocus();
mSearchOption = v.getText().toString().trim();
mCurrentPage = 1;
// 执行搜索
mPresenter.getWaterPlanList(mCurrentPage,mSearchOption);
return true;
}
return false;
});
}
@Override
protected void onResumeInitData() {
super.onResumeInitData();
showLoadingDialog();
mPresenter.getWaterPlanList(mCurrentPage,mSearchOption);
}
private void initListener() {
setClick(viewBinding.tvAdd);
setClick(viewBinding.includedNoresult.btnRefresh);
setClick(viewBinding.includedNoresult.tvAddPlan);
}
private void setClick(View view) {
@@ -65,11 +122,53 @@ public class WaterPlanFragment extends BaseFragment<WaterPlanFragmentBinding, Wa
public void onClick(View v){
switch (v.getId()){
case R.id.tv_add:
case R.id.tv_add_plan:
goTo(mContext, AddWaterPlanActivity.class,null);
break;
case R.id.btn_refresh:
mCurrentPage = 1;
mPresenter.getWaterPlanList(mCurrentPage,mSearchOption);
break;
}
}
@Override
public void getWaterConfigListSuccess(List<WaterPlanWeekEntity> list,int total) {
hideDialogLoading();
List<WaterPlanWeekEntity> pageList = list == null ? new ArrayList<>() : list;
if (mCurrentPage == 1) {
viewBinding.refresh.finishRefresh(300);
mPlanList.clear(); // 只在刷新时清除
mPlanList = pageList;
} else {
viewBinding.refresh.finishLoadMore(300);
mPlanList.addAll(pageList);
}
mAdapter.setNewData(mPlanList);
// 4. 判断是否还有更多数据
if (mAdapter.getItemCount() >= total || pageList.size() == 0) {
// 使用 post 延迟调用,避免内部状态冲突导致的循环调用
viewBinding.refresh.postDelayed(() -> viewBinding.refresh.setNoMoreData(true), 300);
viewBinding.relNoMore.setVisibility(VISIBLE); // 自定义底部提示"暂无更多数据"
} else {
viewBinding.refresh.setNoMoreData(false);
viewBinding.relNoMore.setVisibility(View.GONE);
}
// 5. 控制空布局和内容显示
if (mAdapter.getItemCount() != 0) {
viewBinding.refresh.setVisibility(VISIBLE);
viewBinding.relNoresult.setVisibility(View.GONE);
} else {
viewBinding.refresh.setVisibility(View.GONE);
viewBinding.relNoresult.setVisibility(VISIBLE);
}
}
@Override
public WaterPlanPresenter createPresenter() {
return new WaterPlanPresenter(new WaterPlanImpl());
@@ -82,11 +181,54 @@ public class WaterPlanFragment extends BaseFragment<WaterPlanFragmentBinding, Wa
@Override
public void showError(String message) {
hideDialogLoading();
ToastUtil.showShort(mContext,message);
}
@Override
public void logOut(BaseBean bean) {
}
@Override
public void saveConfigSuccess(WaterPlanWeekEntity entity) {
}
@Override
public void updateConfigSuccess(WaterPlanWeekEntity entity) {
}
@Override
public void updatePlanStatusSuccess(BaseBean bean, String status) {
}
@Override
public void getPlanDetailInfo(WaterPlanWeekEntity entity) {
}
@Override
public void getPlanBindDeviceList(WaterDeviceEntity bean) {
}
@Override
public void planBindDeviceSuccess(BaseBean bean) {
}
@Override
public void deletePlanSuccess(BaseBean bean) {
}
@Override
public void planUnbindDeviceSuccess(BaseBean bean, int position) {
}
}

View File

@@ -8,26 +8,27 @@ import androidx.annotation.Nullable;
import com.chad.library.adapter.base.BaseQuickAdapter;
import com.chad.library.adapter.base.BaseViewHolder;
import com.ckkj.water.R;
import com.ckkj.water.index.entity.WaterDeviceEntity;
import com.ckkj.water.plan.entity.WaterPlanWeekEntity;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class BindDeviceAdapter extends BaseQuickAdapter<WaterPlanWeekEntity.DeviceEntity, BaseViewHolder> {
public class BindDeviceAdapter extends BaseQuickAdapter<WaterDeviceEntity.DeviceListBean, BaseViewHolder> {
private Context mContext;
private Set<Integer> mSelectedPositions = new HashSet<>();
public BindDeviceAdapter(Context context, int layoutResId, @Nullable List<WaterPlanWeekEntity.DeviceEntity> data) {
public BindDeviceAdapter(Context context, int layoutResId, @Nullable List<WaterDeviceEntity.DeviceListBean> data) {
super(layoutResId, data);
this.mContext = context;
}
@Override
protected void convert(BaseViewHolder helper, WaterPlanWeekEntity.DeviceEntity item) {
protected void convert(BaseViewHolder helper, WaterDeviceEntity.DeviceListBean item) {
CheckBox checkBox = helper.getView(R.id.radio);
helper.setText(R.id.tv_device_name, item.getDeviceName());
helper.setText(R.id.tv_device_serial, item.getDeviceCode());
helper.setText(R.id.tv_device_serial, item.getDeviceSn());
checkBox.setChecked(mSelectedPositions.contains(helper.getLayoutPosition()));
}

View File

@@ -0,0 +1,32 @@
package com.ckkj.water.plan.adapter;
import android.content.Context;
import androidx.annotation.Nullable;
import com.chad.library.adapter.base.BaseQuickAdapter;
import com.chad.library.adapter.base.BaseViewHolder;
import com.ckkj.water.R;
import com.ckkj.water.index.entity.WaterDeviceEntity;
import java.util.List;
/**
* @author fengxiaoyang
* @date 2026/5/29
* @description TODO: 描述该类的作用
*/
public class PlanBoundDeviceAdapter extends BaseQuickAdapter<WaterDeviceEntity, BaseViewHolder> {
private Context mContext;
public PlanBoundDeviceAdapter(Context context,int layoutResId, @Nullable List<WaterDeviceEntity> data) {
super(layoutResId, data);
mContext = context;
}
@Override
protected void convert(BaseViewHolder helper, WaterDeviceEntity item) {
helper.setText(R.id.tv_device_name, item.getDeviceName());
helper.setText(R.id.tv_device_serial, item.getDeviceSn());
helper.addOnClickListener(R.id.img_delete);
}
}

View File

@@ -5,19 +5,20 @@ import androidx.annotation.Nullable;
import com.chad.library.adapter.base.BaseQuickAdapter;
import com.chad.library.adapter.base.BaseViewHolder;
import com.ckkj.water.R;
import com.ckkj.water.index.entity.WaterDeviceEntity;
import com.ckkj.water.plan.entity.WaterPlanWeekEntity;
import java.util.List;
public class PlanDetailDeviceAdapter extends BaseQuickAdapter<WaterPlanWeekEntity.DeviceEntity, BaseViewHolder> {
public class PlanDetailDeviceAdapter extends BaseQuickAdapter<WaterDeviceEntity, BaseViewHolder> {
public PlanDetailDeviceAdapter(int layoutResId, @Nullable List<WaterPlanWeekEntity.DeviceEntity> data) {
public PlanDetailDeviceAdapter(int layoutResId, @Nullable List<WaterDeviceEntity> data) {
super(layoutResId, data);
}
@Override
protected void convert(BaseViewHolder helper, WaterPlanWeekEntity.DeviceEntity item) {
protected void convert(BaseViewHolder helper, WaterDeviceEntity item) {
helper.setText(R.id.tv_device_name,item.getDeviceName());
helper.setText(R.id.tv_device_serial,item.getDeviceCode());
helper.setText(R.id.tv_device_serial,item.getDeviceSn());
}
}

View File

@@ -1,24 +1,29 @@
package com.ckkj.water.plan.adapter;
import static android.view.View.INVISIBLE;
import static android.view.View.VISIBLE;
import android.widget.TextView;
import androidx.annotation.Nullable;
import com.chad.library.adapter.base.BaseQuickAdapter;
import com.chad.library.adapter.base.BaseViewHolder;
import com.ckkj.water.R;
import com.ckkj.water.plan.entity.WaterPlanWeekEntity;
import com.ckkj.water.utils.time.ZYTimeUtils;
import java.util.List;
public class PlanDetailTimeAdapter extends BaseQuickAdapter<WaterPlanWeekEntity.WashCycleEntity, BaseViewHolder> {
public class PlanDetailTimeAdapter extends BaseQuickAdapter<WaterPlanWeekEntity.TimeDataBean, BaseViewHolder> {
public PlanDetailTimeAdapter(int layoutResId, @Nullable List<WaterPlanWeekEntity.WashCycleEntity> data) {
public PlanDetailTimeAdapter(int layoutResId, @Nullable List<WaterPlanWeekEntity.TimeDataBean> data) {
super(layoutResId, data);
}
@Override
protected void convert(BaseViewHolder helper, WaterPlanWeekEntity.WashCycleEntity item) {
helper.setText(R.id.tv_week,item.getWeek());
helper.setText(R.id.tv_start_time,item.getTime());
helper.setText(R.id.tv_duration,item.getDuration());
protected void convert(BaseViewHolder helper, WaterPlanWeekEntity.TimeDataBean item) {
helper.setText(R.id.tv_start_time,ZYTimeUtils.formatHHmm(item.getStartTime()));
helper.setText(R.id.tv_duration,item.getDurationMin() + "min");
}
}

View File

@@ -0,0 +1,50 @@
package com.ckkj.water.plan.adapter;
import android.graphics.Rect;
import android.view.View;
import androidx.annotation.Nullable;
import androidx.recyclerview.widget.RecyclerView;
import com.chad.library.adapter.base.BaseQuickAdapter;
import com.chad.library.adapter.base.BaseViewHolder;
import com.ckkj.water.R;
import com.ckkj.water.plan.entity.WaterPlanWeekEntity;
import java.util.List;
public class PlanWeekDaysAdapter extends BaseQuickAdapter<WaterPlanWeekEntity.DetailsBean, BaseViewHolder> {
public PlanWeekDaysAdapter(int layoutResId, @Nullable List<WaterPlanWeekEntity.DetailsBean> data) {
super(layoutResId, data);
}
@Override
protected void convert(BaseViewHolder helper, WaterPlanWeekEntity.DetailsBean item) {
helper.setText(R.id.tv_week_name, item.getWeekName());
RecyclerView rvWeekDatas = helper.getView(R.id.rv_plan_detail_times);
PlanDetailTimeAdapter adapter = new PlanDetailTimeAdapter(R.layout.plan_detail_time_item, item.getTimeData());
rvWeekDatas.setAdapter(adapter);
}
@Override
public void onAttachedToRecyclerView(RecyclerView recyclerView) {
super.onAttachedToRecyclerView(recyclerView);
// 添加透明色分割线高度10px
recyclerView.addItemDecoration(new RecyclerView.ItemDecoration() {
@Override
public void getItemOffsets(Rect outRect, View view,
RecyclerView parent, RecyclerView.State state) {
int position = parent.getChildAdapterPosition(view);
if (position > 0) {
outRect.top = (int) (10 * view.getContext().getResources().getDisplayMetrics().density);
}
}
@Override
public void onDraw(android.graphics.Canvas c, RecyclerView parent, RecyclerView.State state) {
// 不绘制任何内容,保持透明
}
});
}
}

View File

@@ -1,6 +1,4 @@
package com.ckkj.water.plate.adapter;
import android.content.Context;
package com.ckkj.water.plan.adapter;
import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;

View File

@@ -1,6 +1,7 @@
package com.ckkj.water.plan.adapter;
import android.content.Context;
import android.view.View;
import android.widget.CheckBox;
import androidx.annotation.Nullable;
@@ -14,18 +15,29 @@ import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class WaterPlanListAdapter extends BaseQuickAdapter<WaterPlanWeekEntity.DeviceEntity, BaseViewHolder> {
public class WaterPlanListAdapter extends BaseQuickAdapter<WaterPlanWeekEntity, BaseViewHolder> {
private Context mContext;
public WaterPlanListAdapter(Context context, int layoutResId, @Nullable List<WaterPlanWeekEntity.DeviceEntity> data) {
public WaterPlanListAdapter(Context context, int layoutResId, @Nullable List<WaterPlanWeekEntity> data) {
super(layoutResId, data);
this.mContext = context;
}
@Override
protected void convert(BaseViewHolder helper, WaterPlanWeekEntity.DeviceEntity item) {
helper.setText(R.id.tv_device_name, item.getDeviceName());
helper.setText(R.id.tv_device_serial, item.getDeviceCode());
protected void convert(BaseViewHolder helper, WaterPlanWeekEntity item) {
View viewStatus = helper.getView(R.id.view_status_dot);
helper.setText(R.id.tv_device_name, item.getName());
helper.setText(R.id.tv_device_serial, item.getId());
helper.setText(R.id.tv_device_status, item.getStatus().equals("0") ?
mContext.getString(R.string.closed) :
mContext.getString(R.string.device_status_working));
if(item.getStatus().equals("0")){
helper.setTextColor(R.id.tv_device_status,mContext.getResources().getColor(R.color.color_999999));
viewStatus.setBackground(mContext.getResources().getDrawable(R.drawable.shape_status_dot_999999));
}else{
helper.setTextColor(R.id.tv_device_status,mContext.getResources().getColor(R.color.color_24B326));
viewStatus.setBackground(mContext.getResources().getDrawable(R.drawable.shape_status_dot_green));
}
}

View File

@@ -0,0 +1,49 @@
package com.ckkj.water.plan.adapter;
import android.content.Context;
import android.text.TextUtils;
import android.widget.CheckBox;
import android.widget.TextView;
import androidx.annotation.Nullable;
import com.chad.library.adapter.base.BaseQuickAdapter;
import com.chad.library.adapter.base.BaseViewHolder;
import com.ckkj.water.R;
import com.ckkj.water.plan.entity.WaterPlanWeekEntity;
import java.util.List;
/**
* @author fengxiaoyang
* @date 2026/5/28
* @description TODO: 描述该类的作用
*/
public class WaterPlanTimeDataAdapter extends BaseQuickAdapter<WaterPlanWeekEntity.TimeDataBean, BaseViewHolder> {
private Context mContext;
public WaterPlanTimeDataAdapter(Context context,int layoutResId, @Nullable List<WaterPlanWeekEntity.TimeDataBean> data) {
super(layoutResId, data);
mContext = context;
}
@Override
protected void convert(BaseViewHolder helper, WaterPlanWeekEntity.TimeDataBean item) {
TextView tvStartTime = helper.getView(R.id.tv_select_time);
TextView tvPlanDuration = helper.getView(R.id.tv_plan_duration);
if(!TextUtils.isEmpty(item.getStartTime())){
helper.setText(R.id.tv_select_time, item.getStartTime());
}else{
helper.setText(R.id.tv_select_time,"");
tvStartTime.setHint(mContext.getString(R.string.select_water_time));
}
if(item.getDurationMin() != 0){
helper.setText(R.id.tv_plan_duration,item.getDurationMin() + "");
}else{
helper.setText(R.id.tv_plan_duration,"");
tvPlanDuration.setHint(mContext.getString(R.string.input_water_plan_time));
}
helper.addOnClickListener(R.id.tv_select_time);
helper.addOnClickListener(R.id.tv_plan_duration);
}
}

View File

@@ -7,7 +7,9 @@ import static android.view.View.VISIBLE;
import android.content.Context;
import android.text.TextUtils;
import android.view.View;
import android.widget.CheckBox;
import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.annotation.Nullable;
@@ -15,40 +17,71 @@ import com.chad.library.adapter.base.BaseQuickAdapter;
import com.chad.library.adapter.base.BaseViewHolder;
import com.ckkj.water.R;
import com.ckkj.water.plan.entity.WaterPlanWeekEntity;
import com.ckkj.water.utils.time.ZYTimeUtils;
import java.util.ArrayList;
import java.util.List;
public class WaterPlanWeekAdapter extends BaseQuickAdapter<WaterPlanWeekEntity.WashCycleEntity, BaseViewHolder> {
private List<WaterPlanWeekEntity.WashCycleEntity> mList = new ArrayList<>();
public class WaterPlanWeekAdapter extends BaseQuickAdapter<WaterPlanWeekEntity.DetailsBean, BaseViewHolder> {
private List<WaterPlanWeekEntity.DetailsBean> mList = new ArrayList<>();
private Context mContext;
private int mPos = 0;
public WaterPlanWeekAdapter(Context context,int layoutResId, @Nullable List<WaterPlanWeekEntity.WashCycleEntity> data) {
public WaterPlanWeekAdapter(Context context,int layoutResId, @Nullable List<WaterPlanWeekEntity.DetailsBean> data) {
super(layoutResId, data);
this.mContext = context;
this.mList = data;
}
@Override
protected void convert(BaseViewHolder helper, WaterPlanWeekEntity.WashCycleEntity item) {
helper.setText(R.id.tv_week,item.getWeek());
LinearLayout linearItem = helper.getView(R.id.linear_item);
View viewStatus = helper.getView(R.id.view_status);
if(helper.getLayoutPosition() == mPos){
linearItem.setBackground(mContext.getResources().getDrawable(R.drawable.shape_water_period_sel_bg));
viewStatus.setVisibility(VISIBLE);
viewStatus.setBackground(mContext.getResources().getDrawable(R.drawable.shape_green_circle));
protected void convert(BaseViewHolder helper, WaterPlanWeekEntity.DetailsBean item) {
TextView tvStartTime = helper.getView(R.id.tv_select_time);
CheckBox checkBox = helper.getView(R.id.checkbox);
TextView tvPlanDuration = helper.getView(R.id.tv_plan_duration);
helper.setText(R.id.tv_week_name,item.getWeekName());
if(!TextUtils.isEmpty(item.getStartTime())){
helper.setText(R.id.tv_select_time, item.getStartTime());
}else{
linearItem.setBackground(null);
if(!TextUtils.isEmpty(item.getTime()) && !TextUtils.isEmpty(item.getDuration())){
viewStatus.setVisibility(VISIBLE);
viewStatus.setBackground(mContext.getResources().getDrawable(R.drawable.shape_yellow_circle));
}else{
viewStatus.setVisibility(INVISIBLE);
viewStatus.setBackground(null);
}
helper.setText(R.id.tv_select_time,"");
tvStartTime.setHint(mContext.getString(R.string.select_water_time));
}
if(item.getDurationMin() != 0){
helper.setText(R.id.tv_plan_duration,item.getDurationMin() + "");
}else{
helper.setText(R.id.tv_plan_duration,"");
tvPlanDuration.setHint(mContext.getString(R.string.input_water_plan_time));
}
if(item.getStatus().equals("1")){
checkBox.setChecked(true);
}else{
checkBox.setChecked(false);
}
helper.addOnClickListener(R.id.linear_week);
helper.addOnClickListener(R.id.checkbox);
helper.addOnClickListener(R.id.tv_select_time);
helper.addOnClickListener(R.id.tv_plan_duration);
// LinearLayout linearItem = helper.getView(R.id.linear_item);
// View viewStatus = helper.getView(R.id.view_status);
// if(helper.getLayoutPosition() == mPos){
// linearItem.setBackground(mContext.getResources().getDrawable(R.drawable.shape_water_period_sel_bg));
// viewStatus.setVisibility(VISIBLE);
// viewStatus.setBackground(mContext.getResources().getDrawable(R.drawable.shape_green_circle));
// }else{
// linearItem.setBackground(null);
// if(!TextUtils.isEmpty(item.getTime()) && !TextUtils.isEmpty(item.getDuration())){
// viewStatus.setVisibility(VISIBLE);
// viewStatus.setBackground(mContext.getResources().getDrawable(R.drawable.shape_yellow_circle));
// }else{
// viewStatus.setVisibility(INVISIBLE);
// viewStatus.setBackground(null);
// }
// }
}
public void setSelPos(int position) {

View File

@@ -0,0 +1,97 @@
package com.ckkj.water.plan.adapter;
import static android.view.View.INVISIBLE;
import static android.view.View.VISIBLE;
import android.content.Context;
import android.text.TextUtils;
import android.view.View;
import android.widget.CheckBox;
import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.annotation.Nullable;
import com.chad.library.adapter.base.BaseQuickAdapter;
import com.chad.library.adapter.base.BaseViewHolder;
import com.ckkj.water.R;
import com.ckkj.water.plan.entity.WaterPlanWeekEntity;
import java.util.ArrayList;
import java.util.List;
public class WaterPlanWeekAdapter_copy extends BaseQuickAdapter<WaterPlanWeekEntity.DetailsBean, BaseViewHolder> {
private List<WaterPlanWeekEntity.DetailsBean> mList = new ArrayList<>();
private Context mContext;
private int mPos = 0;
public WaterPlanWeekAdapter_copy(Context context, int layoutResId, @Nullable List<WaterPlanWeekEntity.DetailsBean> data) {
super(layoutResId, data);
this.mContext = context;
this.mList = data;
}
@Override
protected void convert(BaseViewHolder helper, WaterPlanWeekEntity.DetailsBean item) {
TextView tvStartTime = helper.getView(R.id.tv_select_time);
CheckBox checkBox = helper.getView(R.id.checkbox);
TextView tvPlanDuration = helper.getView(R.id.tv_plan_duration);
helper.setText(R.id.tv_week_name,item.getWeekName());
LinearLayout linearItem = helper.getView(R.id.linear_item);
View viewStatus = helper.getView(R.id.view_status);
if(helper.getLayoutPosition() == mPos){
linearItem.setBackground(mContext.getResources().getDrawable(R.drawable.shape_water_period_sel_bg));
viewStatus.setVisibility(VISIBLE);
viewStatus.setBackground(mContext.getResources().getDrawable(R.drawable.shape_green_circle));
}else{
linearItem.setBackground(null);
viewStatus.setVisibility(INVISIBLE);
}
// if(!TextUtils.isEmpty(item.getStartTime())){
// helper.setText(R.id.tv_select_time, item.getStartTime());
// }else{
// helper.setText(R.id.tv_select_time,"");
// tvStartTime.setHint(mContext.getString(R.string.select_water_time));
// }
// if(item.getDurationMin() != 0){
// helper.setText(R.id.tv_plan_duration,item.getDurationMin() + "");
// }else{
// helper.setText(R.id.tv_plan_duration,"");
// tvPlanDuration.setHint(mContext.getString(R.string.input_water_plan_time));
// }
//
// if(item.getStatus().equals("1")){
// checkBox.setChecked(true);
// }else{
// checkBox.setChecked(false);
// }
//
// helper.addOnClickListener(R.id.linear_week);
// helper.addOnClickListener(R.id.checkbox);
// helper.addOnClickListener(R.id.tv_select_time);
// helper.addOnClickListener(R.id.tv_plan_duration);
// if(!TextUtils.isEmpty(item.getTime()) && !TextUtils.isEmpty(item.getDuration())){
// viewStatus.setVisibility(VISIBLE);
// viewStatus.setBackground(mContext.getResources().getDrawable(R.drawable.shape_yellow_circle));
// }else{
// viewStatus.setVisibility(INVISIBLE);
// viewStatus.setBackground(null);
// }
}
public void setSelPos(int position) {
this.mPos = position;
notifyDataSetChanged();
}
public int getmPos() {
return mPos;
}
}

View File

@@ -1,152 +1,78 @@
package com.ckkj.water.plan.entity;
import com.ckkj.water.index.entity.WaterDeviceEntity;
import java.io.Serializable;
import java.util.List;
import lombok.Data;
import lombok.NoArgsConstructor;
@NoArgsConstructor
@Data
public class WaterPlanWeekEntity implements Serializable {
/**
* 排程名称
*/
private String scheduleName;
/**
* 状态
* id : 2057637613963182082
* userId : 2056543507514097665
* name : 排程四
* deviceIds : null
* status : 1
* details : [{"createDept":null,"createBy":"2056543507514097665","createTime":"2026-05-22 09:40:10","updateBy":"2056543507514097665","updateTime":"2026-05-22 09:40:10","id":"2057637613963182083","scheduleId":"2057637613963182082","weekday":1,"startTime":"2026-04-11 10:12:12","durationMin":20,"zones":null,"triggerType":"0","status":"1"},{"createDept":null,"createBy":"2056543507514097665","createTime":"2026-05-22 09:40:10","updateBy":"2056543507514097665","updateTime":"2026-05-22 09:40:10","id":"2057637613963182084","scheduleId":"2057637613963182082","weekday":2,"startTime":"2026-04-11 10:12:12","durationMin":20,"zones":null,"triggerType":"0","status":"1"},{"createDept":null,"createBy":"2056543507514097665","createTime":"2026-05-22 09:40:10","updateBy":"2056543507514097665","updateTime":"2026-05-22 09:40:10","id":"2057637613963182085","scheduleId":"2057637613963182082","weekday":3,"startTime":"2026-04-11 10:12:12","durationMin":20,"zones":null,"triggerType":"0","status":"1"}]
*/
private boolean enable;
/**
* 洗水周期列表
*/
private List<WashCycleEntity> washCycleList;
private String id;
private String userId;
private String name;
private List<WaterDeviceEntity> deviceIds;
private List<WaterDeviceEntity> deviceNos;
private String status = "1";
private List<DetailsBean> details;
/**
* 关联设备列表
*/
private List<DeviceEntity> deviceList;
public String getScheduleName() {
return scheduleName;
}
public void setScheduleName(String scheduleName) {
this.scheduleName = scheduleName;
}
public boolean isEnable() {
return enable;
}
public void setEnable(boolean enable) {
this.enable = enable;
}
public List<WashCycleEntity> getWashCycleList() {
return washCycleList;
}
public void setWashCycleList(List<WashCycleEntity> washCycleList) {
this.washCycleList = washCycleList;
}
public List<DeviceEntity> getDeviceList() {
return deviceList;
}
public void setDeviceList(List<DeviceEntity> deviceList) {
this.deviceList = deviceList;
}
/**
* 洗水周期
*/
public static class WashCycleEntity {
@NoArgsConstructor
@Data
public static class DetailsBean implements Serializable{
/**
* 星期
* 如:周一
* createDept : null
* createBy : 2056543507514097665
* createTime : 2026-05-22 09:40:10
* updateBy : 2056543507514097665
* updateTime : 2026-05-22 09:40:10
* id : 2057637613963182083
* scheduleId : 2057637613963182082
* weekday : 1
* startTime : 2026-04-11 10:12:12
* durationMin : 20
* zones : null
* triggerType : 0
* status : 1
*/
private String week;
/**
* 时间
* 如10:30
*/
private String time;
/**
* 时长
* 如10min
*/
private String duration;
public String getWeek() {
return week;
}
public void setWeek(String week) {
this.week = week;
}
public String getTime() {
return time;
}
public void setTime(String time) {
this.time = time;
}
public String getDuration() {
return duration;
}
public void setDuration(String duration) {
this.duration = duration;
}
private Object createDept;
private String createBy;
private String createTime;
private String updateBy;
private String updateTime;
private String id;
private String scheduleId;
private int weekday = 1;
private String weekName;
private String startTime = "";
private int durationMin = 0;
private Object zones;
private String triggerType = "0";
private String status = "1";
private List<TimeDataBean> timeData;
}
/**
* 设备实体
*/
public static class DeviceEntity {
/**
* 设备名称
*/
private String deviceName;
/**
* 设备编号
*/
private String deviceCode;
/**
* 是否已关联
*/
private boolean bind;
public String getDeviceName() {
return deviceName;
}
public void setDeviceName(String deviceName) {
this.deviceName = deviceName;
}
public String getDeviceCode() {
return deviceCode;
}
public void setDeviceCode(String deviceCode) {
this.deviceCode = deviceCode;
}
public boolean isBind() {
return bind;
}
public void setBind(boolean bind) {
this.bind = bind;
}
@NoArgsConstructor
@Data
public static class TimeDataBean implements Serializable{
private String startTime = "";
private int durationMin = 0;
private String weekName;
}
}

View File

@@ -1,15 +1,59 @@
package com.ckkj.water.plan.mvp;
import com.ckkj.water.base.IView;
import com.ckkj.water.index.entity.WaterDeviceEntity;
import com.ckkj.water.network.BaseBean;
import com.ckkj.water.plan.entity.WaterPlanWeekEntity;
import org.json.JSONObject;
import java.util.List;
import java.util.Map;
public class WaterPlanContract {
public interface CallBack<T> {
void success(T msg);
void success(T msg,int total);
void fail(String msg);
}
public interface DataModel{
//查询排程列表
void getWaterConfigList(Map<String, String> map,CallBack callBack);
//新增排程
void saveConfig(JSONObject json,CallBack callBack);
//更新排程
void updateConfig(JSONObject json,CallBack callBack);
//更新排程状态
void updatePlanStatus(JSONObject json, CallBack callBack);
//查询排程可绑定的设备列表
void getPlanBindDeviceList(Map<String, String> map,CallBack callBack);
//查询排程详情
void getPlanDetailInfo(Map<String, String> map,CallBack callBack);
//排程绑定设备
void planBindDevice(JSONObject json,CallBack callBack);
//删除排程
void deletePlan(String id,CallBack callBack);
//排程解绑设备
void planUnbindDevice(Map<String, String> map,CallBack callBack);
}
public interface WaterPlanView extends IView {
//查询排程列表成功
void getWaterConfigListSuccess(List<WaterPlanWeekEntity> list,int total);
//排程保存成功g
void saveConfigSuccess(WaterPlanWeekEntity entity);
//排程更新成功
void updateConfigSuccess(WaterPlanWeekEntity entity);
//更新排程状态成功
void updatePlanStatusSuccess(BaseBean bean, String status);
//获取排程详情
void getPlanDetailInfo(WaterPlanWeekEntity entity);
//查询到可绑定设备列表
void getPlanBindDeviceList(WaterDeviceEntity bean);
//排程绑定设备成功
void planBindDeviceSuccess(BaseBean bean);
//删除排程成功
void deletePlanSuccess(BaseBean bean);
//排程解绑设备成功
void planUnbindDeviceSuccess(BaseBean bean,int position);
}
}

View File

@@ -1,7 +1,340 @@
package com.ckkj.water.plan.mvp;
import com.ckkj.water.device.mvp.DeviceContract;
import com.ckkj.water.index.entity.WaterDeviceEntity;
import com.ckkj.water.network.BaseBean;
import com.ckkj.water.network.NetWorkManager;
import com.ckkj.water.plan.entity.WaterPlanWeekEntity;
import org.json.JSONObject;
import java.util.List;
import java.util.Map;
import io.reactivex.Observer;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.annotations.NonNull;
import io.reactivex.disposables.Disposable;
import io.reactivex.schedulers.Schedulers;
public class WaterPlanImpl implements WaterPlanContract.DataModel{
/**
* 查询排程列表
* @param map
* @param callBack
*/
@Override
public void getWaterConfigList(Map<String, String> map, WaterPlanContract.CallBack callBack) {
NetWorkManager.getRequest().scheduleList(NetWorkManager.getToken(),map)
.subscribeOn(Schedulers.io())
.unsubscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<BaseBean<List<WaterPlanWeekEntity>>>() {
@Override
public void onSubscribe(@NonNull Disposable d) {
}
@Override
public void onNext(@NonNull BaseBean<List<WaterPlanWeekEntity>> bean) {
if (bean.getCode() == 200) {
callBack.success(bean.getRows(),bean.getTotal());
}
}
@Override
public void onError(@NonNull Throwable e) {
callBack.fail(e.getMessage());
}
@Override
public void onComplete() {
}
});
}
/**
* 新增排程
* @param json
* @param callBack
*/
@Override
public void saveConfig(JSONObject json, WaterPlanContract.CallBack callBack) {
try {
NetWorkManager.getRequest().addSchedule(NetWorkManager.getToken(),NetWorkManager.toRequestBody(json))
.subscribeOn(Schedulers.io())
.unsubscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<BaseBean<WaterPlanWeekEntity>>() {
@Override
public void onSubscribe(@NonNull Disposable d) {
}
@Override
public void onNext(@NonNull BaseBean<WaterPlanWeekEntity> bean) {
if (bean.getCode() == 200) {
callBack.success(bean.getData(),0);
} else {
callBack.fail(bean.getMessage());
}
}
@Override
public void onError(@NonNull Throwable e) {
callBack.fail(e.getMessage());
}
@Override
public void onComplete() {
}
});
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 更新排程信息
* @param json
* @param callBack
*/
@Override
public void updateConfig(JSONObject json, WaterPlanContract.CallBack callBack) {
try {
NetWorkManager.getRequest().updateSchedule(NetWorkManager.getToken(),NetWorkManager.toRequestBody(json))
.subscribeOn(Schedulers.io())
.unsubscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<BaseBean<WaterPlanWeekEntity>>() {
@Override
public void onSubscribe(@NonNull Disposable d) {
}
@Override
public void onNext(@NonNull BaseBean<WaterPlanWeekEntity> bean) {
if (bean.getCode() == 200) {
callBack.success(bean.getData(),0);
} else {
callBack.fail(bean.getMessage());
}
}
@Override
public void onError(@NonNull Throwable e) {
callBack.fail(e.getMessage());
}
@Override
public void onComplete() {
}
});
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 更新排程状态
* @param callBack
*/
@Override
public void updatePlanStatus(JSONObject json, WaterPlanContract.CallBack callBack) {
NetWorkManager.getRequest().updateScheduleStatus(NetWorkManager.getToken(),NetWorkManager.toRequestBody(json))
.subscribeOn(Schedulers.io())
.unsubscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<BaseBean<WaterPlanWeekEntity>>() {
@Override
public void onSubscribe(@NonNull Disposable d) {
}
@Override
public void onNext(@NonNull BaseBean<WaterPlanWeekEntity> bean) {
if (bean.getCode() == 200) {
callBack.success(bean.getData(), 0);
} else {
callBack.fail(bean.getMessage());
}
}
@Override
public void onError(@NonNull Throwable e) {
callBack.fail(e.getMessage());
}
@Override
public void onComplete() {
}
});
}
/**
* 查询可绑定排程的设备列表
* @param map
* @param callBack
*/
@Override
public void getPlanBindDeviceList(Map<String, String> map, WaterPlanContract.CallBack callBack) {
String deviceID = map.get("id");
NetWorkManager.getRequest().getPlanBindDeviceList(NetWorkManager.getToken(), deviceID)
.subscribeOn(Schedulers.io())
.unsubscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<BaseBean<WaterDeviceEntity>>() {
@Override
public void onSubscribe(@NonNull Disposable d) {
}
@Override
public void onNext(@NonNull BaseBean<WaterDeviceEntity> bean) {
if (bean.getCode() == 200) {
callBack.success(bean.getData(),0);
}
}
@Override
public void onError(@NonNull Throwable e) {
callBack.fail(e.getMessage());
}
@Override
public void onComplete() {
}
});
}
@Override
public void getPlanDetailInfo(Map<String, String> map, WaterPlanContract.CallBack callBack) {
String deviceID = map.get("id");
NetWorkManager.getRequest().getPlanDetailInfo(NetWorkManager.getToken(), deviceID)
.subscribeOn(Schedulers.io())
.unsubscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<BaseBean<WaterPlanWeekEntity>>() {
@Override
public void onSubscribe(@NonNull Disposable d) {
}
@Override
public void onNext(@NonNull BaseBean<WaterPlanWeekEntity> bean) {
if (bean.getCode() == 200) {
callBack.success(bean.getData(),0);
}
}
@Override
public void onError(@NonNull Throwable e) {
callBack.fail(e.getMessage());
}
@Override
public void onComplete() {
}
});
}
@Override
public void planBindDevice(JSONObject json, WaterPlanContract.CallBack callBack) {
try {
NetWorkManager.getRequest().planBindDevice(NetWorkManager.getToken(),NetWorkManager.toRequestBody(json))
.subscribeOn(Schedulers.io())
.unsubscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<BaseBean>() {
@Override
public void onSubscribe(@NonNull Disposable d) {
}
@Override
public void onNext(@NonNull BaseBean bean) {
if (bean.getCode() == 200) {
callBack.success(bean.getData(),0);
} else {
callBack.fail(bean.getMessage());
}
}
@Override
public void onError(@NonNull Throwable e) {
callBack.fail(e.getMessage());
}
@Override
public void onComplete() {
}
});
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 删除排程
* @param id
* @param callBack
*/
@Override
public void deletePlan(String id, WaterPlanContract.CallBack callBack) {
try {
NetWorkManager.getRequest().deletePlanById(NetWorkManager.getToken(), id)
.subscribeOn(Schedulers.io())
.unsubscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<BaseBean>() {
@Override
public void onSubscribe(@NonNull Disposable d) {
}
@Override
public void onNext(@NonNull BaseBean bean) {
if (bean.getCode() == 200) {
callBack.success(bean,0);
} else {
callBack.fail(bean.getMessage());
}
}
@Override
public void onError(@NonNull Throwable e) {
callBack.fail(e.getMessage());
}
@Override
public void onComplete() {
}
});
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void planUnbindDevice(Map<String, String> map, WaterPlanContract.CallBack callBack) {
NetWorkManager.getRequest().planUnBindDevice(NetWorkManager.getToken(), map)
.subscribeOn(Schedulers.io())
.unsubscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<BaseBean>() {
@Override
public void onSubscribe(@NonNull Disposable d) {
}
@Override
public void onNext(@NonNull BaseBean bean) {
if (bean.getCode() == 200) {
callBack.success(bean,0);
} else {
callBack.fail(bean.getMessage());
}
}
@Override
public void onError(@NonNull Throwable e) {
callBack.fail(e.getMessage());
}
@Override
public void onComplete() {
}
});
}
}

View File

@@ -1,8 +1,17 @@
package com.ckkj.water.plan.mvp;
import com.ckkj.water.base.BasePresenter;
import com.ckkj.water.device.mvp.DeviceContract;
import com.ckkj.water.device.mvp.DeviceImpl;
import com.ckkj.water.index.entity.WaterDeviceEntity;
import com.ckkj.water.network.BaseBean;
import com.ckkj.water.plan.entity.WaterPlanWeekEntity;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class WaterPlanPresenter extends BasePresenter<WaterPlanContract.WaterPlanView> {
private WaterPlanImpl impl;
@@ -10,4 +19,291 @@ public class WaterPlanPresenter extends BasePresenter<WaterPlanContract.WaterPla
public WaterPlanPresenter(WaterPlanImpl impl) {
this.impl = impl;
}
/**
* 获取排程信息
*/
public void getWaterPlanList(int mCurrentPage,String searchOption) {
Map<String,String> map = new HashMap<>();
map.put("pageNum", mCurrentPage + "");
map.put("pageSize", "10");
map.put("name", searchOption);
impl.getWaterConfigList(map, new WaterPlanContract.CallBack<List<WaterPlanWeekEntity>>() {
@Override
public void success(List<WaterPlanWeekEntity> List, int total) {
if(WaterPlanPresenter.this.getView() != null){
WaterPlanPresenter.this.getView().getWaterConfigListSuccess(List, total);
}
}
@Override
public void fail(String msg) {
if(WaterPlanPresenter.this.getView() != null){
WaterPlanPresenter.this.getView().showError(msg);
}
}
});
}
/**
* 保存排程信息
* @param entity
*/
public void saveConfig(WaterPlanWeekEntity entity) {
try {
JSONObject json = new JSONObject();
json.put("name", entity.getName());
json.put("status", entity.getStatus());
JSONArray array = new JSONArray();
for(WaterPlanWeekEntity.DetailsBean detailsBean : entity.getDetails()){
JSONObject jsonDetails = new JSONObject();
jsonDetails.put("weekday", detailsBean.getWeekday());
jsonDetails.put("triggerType", detailsBean.getTriggerType());
jsonDetails.put("status", detailsBean.getStatus());
JSONArray timeArray = new JSONArray();
for(WaterPlanWeekEntity.TimeDataBean timeDataBean : detailsBean.getTimeData()){
JSONObject jsonTime = new JSONObject();
jsonTime.put("startTime", timeDataBean.getStartTime());
jsonTime.put("durationMin", timeDataBean.getDurationMin());
timeArray.put(jsonTime);
}
jsonDetails.put("timeData", timeArray);
array.put(jsonDetails);
}
json.put("details", array);
impl.saveConfig(json, new WaterPlanContract.CallBack<WaterPlanWeekEntity>() {
@Override
public void success(WaterPlanWeekEntity bean, int total) {
if(WaterPlanPresenter.this.getView() != null){
WaterPlanPresenter.this.getView().saveConfigSuccess(bean);
}
}
@Override
public void fail(String msg) {
if(WaterPlanPresenter.this.getView() != null){
WaterPlanPresenter.this.getView().showError(msg);
}
}
});
} catch (JSONException e) {
throw new RuntimeException(e);
}
}
/**
* 更新排程信息
* @param entity
*/
public void updateConfig(WaterPlanWeekEntity entity) {
try {
JSONObject json = new JSONObject();
json.put("id", entity.getId());
json.put("name", entity.getName());
json.put("status", entity.getStatus());
JSONArray array = new JSONArray();
for(WaterPlanWeekEntity.DetailsBean detailsBean : entity.getDetails()){
JSONObject jsonDetails = new JSONObject();
jsonDetails.put("weekday", detailsBean.getWeekday());
jsonDetails.put("triggerType", detailsBean.getTriggerType());
jsonDetails.put("status", detailsBean.getStatus());
jsonDetails.put("id", detailsBean.getId());
JSONArray timeArray = new JSONArray();
for(WaterPlanWeekEntity.TimeDataBean timeDataBean : detailsBean.getTimeData()){
JSONObject jsonTime = new JSONObject();
jsonTime.put("startTime", timeDataBean.getStartTime());
jsonTime.put("durationMin", timeDataBean.getDurationMin());
timeArray.put(jsonTime);
}
jsonDetails.put("timeData", timeArray);
array.put(jsonDetails);
}
json.put("details", array);
impl.updateConfig(json, new WaterPlanContract.CallBack<WaterPlanWeekEntity>() {
@Override
public void success(WaterPlanWeekEntity bean, int total) {
if(WaterPlanPresenter.this.getView() != null){
WaterPlanPresenter.this.getView().updateConfigSuccess(bean);
}
}
@Override
public void fail(String msg) {
if(WaterPlanPresenter.this.getView() != null){
WaterPlanPresenter.this.getView().showError(msg);
}
}
});
} catch (JSONException e) {
throw new RuntimeException(e);
}
}
/**
* 查询排程可绑定的设备列表
* @param entity
*/
public void getPlanBindDevices(WaterPlanWeekEntity entity) {
Map<String,String> map = new HashMap<>();
map.put("id",entity.getId());
impl.getPlanBindDeviceList(map, new WaterPlanContract.CallBack<WaterDeviceEntity>() {
@Override
public void success(WaterDeviceEntity bean, int total) {
if(WaterPlanPresenter.this.getView() != null){
WaterPlanPresenter.this.getView().getPlanBindDeviceList(bean);
}
}
@Override
public void fail(String msg) {
if(WaterPlanPresenter.this.getView() != null){
WaterPlanPresenter.this.getView().showError( msg);
}
}
});
}
/**
* 查询排程详情
* @param mPlanEntity
*/
public void getPlanDetailInfo(WaterPlanWeekEntity mPlanEntity) {
Map<String,String> map = new HashMap<>();
map.put("id",mPlanEntity.getId());
impl.getPlanDetailInfo(map, new WaterPlanContract.CallBack<WaterPlanWeekEntity>() {
@Override
public void success(WaterPlanWeekEntity bean, int total) {
if(WaterPlanPresenter.this.getView() != null){
WaterPlanPresenter.this.getView().getPlanDetailInfo(bean);
}
}
@Override
public void fail(String msg) {
if(WaterPlanPresenter.this.getView() != null){
WaterPlanPresenter.this.getView().showError( msg);
}
}
});
}
/**
* 排程绑定设备
* @param entity
* @param deviceNo
*/
public void planBindWithDevices(WaterPlanWeekEntity entity, String deviceNo) {
try {
JSONObject json = new JSONObject();
json.put("scheduleId", entity.getId());
// 将逗号分隔的字符串转换为 JSONArray (数字类型)
JSONArray deviceIdArray = new JSONArray();
String[] idArray = deviceNo.split(",");
for (String id : idArray) {
deviceIdArray.put(id);
}
json.put("deviceNos", deviceIdArray);
impl.planBindDevice(json, new WaterPlanContract.CallBack<BaseBean>() {
@Override
public void success(BaseBean bean, int total) {
if(WaterPlanPresenter.this.getView() != null){
WaterPlanPresenter.this.getView().planBindDeviceSuccess(bean);
}
}
@Override
public void fail(String msg) {
if(WaterPlanPresenter.this.getView() != null){
WaterPlanPresenter.this.getView().showError( msg);
}
}
});
} catch (JSONException e) {
throw new RuntimeException(e);
}
}
/**
* 更新排程状态
* @param entity 排程实体
* @param status 状态 0-关闭 1-开启
*/
public void updatePlanStatus(WaterPlanWeekEntity entity, String status) {
try {
JSONObject json = new JSONObject();
json.put("id", entity.getId());
json.put("status", status);
impl.updatePlanStatus(json, new WaterPlanContract.CallBack<BaseBean>() {
@Override
public void success(BaseBean bean, int total) {
if (WaterPlanPresenter.this.getView() != null) {
WaterPlanPresenter.this.getView().updatePlanStatusSuccess(bean,status);
}
}
@Override
public void fail(String msg) {
if (WaterPlanPresenter.this.getView() != null) {
WaterPlanPresenter.this.getView().showError(msg);
}
}
});
} catch (JSONException e) {
throw new RuntimeException(e);
}
}
/**
* 删除排程
* @param mDetailEntity
*/
public void deletePlan(WaterPlanWeekEntity mDetailEntity) {
impl.deletePlan(mDetailEntity.getId(), new WaterPlanContract.CallBack<BaseBean>() {
@Override
public void success(BaseBean bean, int total) {
if(WaterPlanPresenter.this.getView() != null){
WaterPlanPresenter.this.getView().deletePlanSuccess(bean);
}
}
@Override
public void fail(String msg) {
if(WaterPlanPresenter.this.getView() != null){
WaterPlanPresenter.this.getView().showError( msg);
}
}
});
}
/**
* 排程解绑设备
* @param planID
* @param deviceID
*/
public void planUnbindDevice(String planID, String deviceID,int position) {
Map<String,String> map = new HashMap<>();
map.put("scheduleId",planID);
map.put("deviceNo",deviceID);
impl.planUnbindDevice(map, new WaterPlanContract.CallBack<BaseBean>() {
@Override
public void success(BaseBean bean, int total) {
if(WaterPlanPresenter.this.getView() != null){
WaterPlanPresenter.this.getView().planUnbindDeviceSuccess(bean,position);
}
}
@Override
public void fail(String msg) {
if(WaterPlanPresenter.this.getView() != null){
WaterPlanPresenter.this.getView().showError( msg);
}
}
});
}
}

View File

@@ -1,114 +0,0 @@
//package com.ckkj.water.plate;
//
//import android.os.Bundle;
//import android.view.View;
//
//import androidx.annotation.NonNull;
//import androidx.fragment.app.Fragment;
//
//import com.ckkj.water.AppConfig;
//import com.ckkj.water.R;
//import com.ckkj.water.base.BaseFragment;
//import com.ckkj.water.databinding.PlateFragmentBinding;
//import com.ckkj.water.login.LoginActivity;
//import com.ckkj.water.network.BaseBean;
//import com.ckkj.water.plate.adapter.ViewPagerAdapter;
//import com.ckkj.water.plate.entity.BaziResultBean;
//import com.ckkj.water.plate.entity.BaziSaveSuccessEntity;
//import com.ckkj.water.plate.entity.PaipanHistoryEntity;
//import com.ckkj.water.plate.mvp.PlateContract;
//import com.ckkj.water.plate.mvp.PlateImpl;
//import com.ckkj.water.plate.mvp.PlatePresenter;
//
//import java.util.ArrayList;
//import java.util.List;
//
//
///**
// * @author fengxiaoyang
// * @date 2025/7/30
// * @description TODO: 排盘页面
// */
//
//public class PlateFragment extends BaseFragment<PlateFragmentBinding, PlatePresenter>
// implements PlateContract.PlateView {
// private List<Fragment> mFragmentList = new ArrayList<>();
//
// @Override
// public PlatePresenter createPresenter() {
// return new PlatePresenter(new PlateImpl());
// }
//
// @Override
// public void initData(Bundle state) {
// viewBinding.includedTitle.imgBack.setVisibility(View.GONE);
// viewBinding.includedTitle.tvTitle.setText("信息录入");
// ViewPagerAdapter adapter = new ViewPagerAdapter(this, mFragmentList);
// viewBinding.viewpage.setAdapter(adapter);
// viewBinding.tvPaipan.setSelected(true);
// viewBinding.viewpage.setCurrentItem(0);
// //viewpage2 特有的 api禁止滑动
// viewBinding.viewpage.setUserInputEnabled(false);
// }
//
//
// @Override
// public void onNetChange(int netModel) {
//
// }
//
// @Override
// public void showError(String message) {
//
// }
//
// @Override
// public void logOut(BaseBean bean) {
//
// }
//
// @Override
// public void getPaipanResult(BaziResultBean bean) {
//
// }
//
// @Override
// public void saveBaziResultSuccess(BaziSaveSuccessEntity bean) {
//
// }
//
// @Override
// public void getHistorySuccess(PaipanHistoryEntity entity) {
//
// }
//
// @Override
// public void deletePaipanHistorySuccess(int pos) {
//
// }
//
// @Override
// public void onStreamMessageReceived(String messageChunk) {
//
// }
//
// @Override
// public void onStreamComplete(String complateMsg) {
//
// }
//
// @Override
// public void commitReportSuccess(BaseBean bean) {
//
// }
//
// @Override
// public void onPermissionsGranted(int requestCode, @NonNull List<String> perms) {
//
// }
//
// @Override
// public void onPermissionsDenied(int requestCode, @NonNull List<String> perms) {
//
// }
//}

View File

@@ -1,40 +0,0 @@
package com.ckkj.water.plate.adapter;
import android.content.Context;
import android.graphics.Color;
import androidx.annotation.Nullable;
import com.chad.library.adapter.base.BaseQuickAdapter;
import com.chad.library.adapter.base.BaseViewHolder;
import com.ckkj.water.R;
import com.ckkj.water.utils.helper.FiveElementsHelper;
import java.util.List;
/**
* @author fengxiaoyang
* @date 2025/8/6
* @description TODO: 描述该类的作用
*/
public class CangGanAdapter extends BaseQuickAdapter<String, BaseViewHolder> {
private Context mContext;
private List<String> mDzGodList;
public CangGanAdapter(Context context, int layoutResId, @Nullable List<String> data,List<String> dzGodList) {
super(layoutResId, data);
this.mContext = context;
this.mDzGodList = dzGodList;
}
public void setmDzGodList(List<String> mDzGodList) {
this.mDzGodList = mDzGodList;
}
@Override
protected void convert(BaseViewHolder holder, String item) {
holder.setText(R.id.tv_cg_gan,item);
holder.setTextColor(R.id.tv_cg_gan, Color.parseColor(FiveElementsHelper.getElementInfo(item).get("color")));
holder.setText(R.id.tv_cg_shishen,mDzGodList.get(holder.getLayoutPosition()));
}
}

Some files were not shown because too many files have changed in this diff Show More