Compare commits

...

39 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
162 changed files with 5104 additions and 7238 deletions

View File

@@ -4,10 +4,10 @@
<selectionStates>
<SelectionState runConfigName="app">
<option name="selectionMode" value="DROPDOWN" />
<DropdownSelection timestamp="2026-06-06T06:46:42.891310900Z">
<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

@@ -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}"

Binary file not shown.

View File

@@ -35,6 +35,7 @@
<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" />
@@ -125,7 +126,7 @@
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"
@@ -170,10 +171,6 @@
android:name="com.ckkj.water.device.AddDeviceActivity"
android:screenOrientation="portrait"
android:windowSoftInputMode="adjustResize"/>
<activity
android:name="com.ckkj.water.device.AddDeviceActivity_copy"
android:screenOrientation="portrait"
android:windowSoftInputMode="adjustResize"/>
<activity
android:name="com.ckkj.water.device.SelectWifiActivity"
android:screenOrientation="portrait"

View File

@@ -15,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;
@@ -113,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=";

View File

@@ -41,6 +41,7 @@ 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;
//相机权限

View File

@@ -11,12 +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;
@@ -71,6 +71,9 @@ public class MyApplication extends Application {
// 恢复应用语言设置
applyStoredLocale();
// 检查并设置默认主题色(如果之前没有设置过,默认设为白色主题)
applyDefaultTheme();
boolean isUserAgreed = SharePreUtil.getBoolean(ConstantUtil.SHARE_PRE_NAME,context,ConstantUtil.PRIVACY_POLICY_AGREED);
if(isUserAgreed){
initializeUmengSDK();
@@ -153,11 +156,11 @@ 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");
}
@@ -190,4 +193,18 @@ public class MyApplication extends Application {
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

@@ -194,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状态如果正在销毁则不处理
@@ -546,10 +547,9 @@ public abstract class BaseActivity<T extends ViewBinding, P extends IPresenter>
editText.requestFocus();
//设置输入类型
setEditInputType(editText,inputType);
if(TextUtils.isEmpty(content)){
editText.setHint(hint);
}else{
if(!TextUtils.isEmpty(content)){
editText.setText(content);
}
if (!TextUtils.isEmpty(content)) {
@@ -1201,6 +1201,7 @@ public abstract class BaseActivity<T extends ViewBinding, P extends IPresenter>
editText.setInputType(
InputType.TYPE_CLASS_NUMBER
);
editText.setFilters(new InputFilter[]{new InputFilter.LengthFilter(4)});
break;
case INPUT_TYPE_LETTER:
@@ -1251,6 +1252,10 @@ public abstract class BaseActivity<T extends ViewBinding, P extends IPresenter>
});
break;
case INPUT_TYPE_NORMAL:
editText.setFilters(new InputFilter[]{new InputFilter.LengthFilter(20)});
break;
default:
editText.setInputType(
InputType.TYPE_CLASS_TEXT

View File

@@ -22,6 +22,7 @@ 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;
@@ -100,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);
}
/**
* 获取权限
*
@@ -145,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是否真正对用户可见
*/
@@ -901,10 +950,9 @@ public abstract class BaseFragment<T extends ViewBinding,P extends IPresenter> e
//设置输入类型
setEditInputType(editText,inputType);
if(TextUtils.isEmpty(content)){
editText.setHint(hint);
}else{
if(!TextUtils.isEmpty(content)){
editText.setText(content);
editText.setSelection(content.length());
}
@@ -968,6 +1016,16 @@ public abstract class BaseFragment<T extends ViewBinding,P extends IPresenter> e
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
);

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);
}
}
@@ -110,10 +130,6 @@ public class CustomTypeFilterPopupView extends PartShadowPopupView implements Vi
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,20 +4,33 @@ 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;
@@ -25,6 +38,7 @@ 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;
@@ -33,9 +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.ble.BleManager;
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;
/**
@@ -43,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());
@@ -52,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) // 设置状态栏颜色
@@ -59,35 +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() {
initListener();
}
/**
* 初始化监听g
*/
private void initListener() {
setClick(viewBinding.includedTitle.imgBack);
setClick(viewBinding.tvScanAdd);
setClick(viewBinding.btnBleScan);
if(bleAdapter != null){
bleAdapter.setOnItemClickListener(new BaseQuickAdapter.OnItemClickListener() {
@Override
public void run() {
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", "停止扫描");
}
},3000);
initListener();
}
private void initListener() {
setClick(viewBinding.includedTitle.imgBack);
setClick(viewBinding.tvScanAdd);
/**
* 初始化蓝牙适配器
*/
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);
}
@@ -98,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;
@@ -114,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, "需要蓝牙权限才能扫描设备");
}
}
}
@@ -170,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){
}
}
@@ -190,7 +424,7 @@ public class AddDeviceActivity extends BaseActivity<AddDeviceLayoutBinding, Devi
}
@Override
public void addDeviceSuccess(BaseBean bean) {
public void addDeviceSuccess(WaterDeviceEntity bean) {
}
@@ -210,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

@@ -1,463 +0,0 @@
package com.ckkj.water.device;
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.bluetooth.le.BluetoothLeScanner;
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.view.View;
import android.widget.ImageView;
import android.widget.Toast;
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.BuildConfig;
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;
import com.maning.mlkitscanner.scan.callback.act.MNScanCallback;
import org.jetbrains.annotations.NotNull;
import java.util.Arrays;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.UUID;
import no.nordicsemi.android.ble.observer.ConnectionObserver;
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;
/**
* 添加设备页面
*/
public class AddDeviceActivity_copy 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());
}
@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) // 设置状态栏颜色
.statusBarDarkFont(ThemeManager.isAppThemeLight(mContext)) // 设置状态栏字体为黑色
.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();
}
initListener();
}
/**
* 初始化监听g
*/
private void initListener() {
setClick(viewBinding.includedTitle.imgBack);
setClick(viewBinding.tvScanAdd);
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());
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)) {
return;
}
discoveredMacSet.add(deviceAddress);
WaterDeviceEntity bean = new WaterDeviceEntity();
//设备名字
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(null, 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);
}
public void onClick(View v){
switch (v.getId()){
case R.id.img_back:
finish();
break;
case R.id.tv_scan_add:
//检测有无相机权限
String readPermission = Manifest.permission.CAMERA;
if(!hasRecordPermission(readPermission)){
getPermissionRequst(readPermission,"权限申请",
"智能浇水需要您的授权访问相机,并使用扫一扫",REQUEST_EVENT_CODE_10001);
}else{
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, "需要蓝牙权限才能扫描设备");
}
}
}
private void scanQrcode() {
//默认扫描
MNScanManager.startScan(mContext, new MNScanCallback() {
@Override
public void onActivityResult(int resultCode, Intent data) {
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());
}
break;
case MNScanManager.RESULT_FAIL:
String resultError = data.getStringExtra(MNScanManager.INTENT_KEY_RESULT_ERROR);
break;
case MNScanManager.RESULT_CANCLE:
ToastUtil.showShort(mContext,"取消扫码");
break;
}
}
});
}
@Override
protected void onPause() {
super.onPause();
// 停止帧动画
ImageView ivScanAnimation = viewBinding.ivScanAnimation;
if (ivScanAnimation.getDrawable() instanceof AnimationDrawable) {
AnimationDrawable animationDrawable = (AnimationDrawable) ivScanAnimation.getDrawable();
if (animationDrawable.isRunning()) {
animationDrawable.stop();
}
}
}
@Override
public int getLayoutResId(Bundle savedInstanceState) {
return 0;
}
@Override
public void showError(String message) {
}
@Override
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_10002){
}
}
@Override
public void onPermissionsDenied(int requestCode, @NonNull List<String> perms) {
}
@Override
public void addDeviceSuccess(BaseBean bean) {
}
@Override
public void getDeviceDetailInfo(WaterDeviceEntity bean) {
}
@Override
public void editDeviceInfoSuccess(BaseBean bean) {
}
@Override
public void deleteDeviceSuccess(BaseBean bean) {
}
@Override
public void turnOnOffDeviceSuccess(BaseBean 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,9 +17,12 @@ 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;
import com.gyf.immersionbar.ImmersionBar;
/**
@@ -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.ivConnectAnimation.setImageResource(R.drawable.anim_connect_device);
animationDrawable = (AnimationDrawable) viewBinding.ivConnectAnimation.getDrawable();
if (animationDrawable != null) {
animationDrawable.start();
handler.postDelayed(() -> {
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();
}
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);
new Handler().postDelayed(new Runnable() {
}
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();
}
}
@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,7 @@ public class DeviceConnectActivity extends BaseActivity<DeviceConnectLayoutBindi
}
@Override
public void addDeviceSuccess(BaseBean bean) {
public void addDeviceSuccess(WaterDeviceEntity bean) {
}
@@ -119,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

@@ -2,6 +2,8 @@ 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;
@@ -21,15 +23,19 @@ 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.plan.entity.WaterPlanWeekEntity;
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 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;
@@ -40,12 +46,37 @@ import de.greenrobot.event.ThreadMode;
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());
@@ -59,17 +90,15 @@ public class DeviceControlActivity extends BaseActivity<DeviceControlLayoutBindi
mDeviceEntity = (WaterDeviceEntity) bundle.getSerializable("device_info");
if(mDeviceEntity != null){
showLoadingDialog();
mPresenter.getDeviceDetailInfo(mDeviceEntity.getId());
viewBinding.includedTitle.tvTitle.setText(mDeviceEntity.getDeviceName());
//查询设备详情
mPresenter.getDeviceDetailInfo(mDeviceEntity.getDeviceNo());
//查询设备当前工作进度
if(mDeviceEntity.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));
mPresenter.getDeviceWorkProgress(mDeviceEntity.getDeviceNo());
}
viewBinding.includedTitle.tvTitle.setText(mDeviceEntity.getDeviceName());
updateDeviceStatus(mDeviceEntity);
}
}
mTimeList.add("1min");
@@ -97,6 +126,11 @@ public class DeviceControlActivity extends BaseActivity<DeviceControlLayoutBindi
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));
@@ -111,6 +145,35 @@ public class DeviceControlActivity extends BaseActivity<DeviceControlLayoutBindi
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);
@@ -138,7 +201,21 @@ public class DeviceControlActivity extends BaseActivity<DeviceControlLayoutBindi
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:
@@ -151,31 +228,23 @@ public class DeviceControlActivity extends BaseActivity<DeviceControlLayoutBindi
.isDestroyOnDismiss(true) //对于只使用一次的弹窗,推荐设置这个
.atView(viewBinding.linearBat)
.hasShadowBg(false) // 去掉半透明背景
.asCustom(new CustomBubbleAttachPopup(mContext,"设备电量:"+
.asCustom(new CustomBubbleAttachPopup(mContext,getString(R.string.device_battery)+
mDeviceEntity.getPowerLevel() + "%" +
" 更新时间: 05- 11 18:00"))
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:
if(mCustomDuration == 0 && mAdapter.getmSelPostion() == -1){
ToastUtil.showShort(mContext,getString(R.string.select_watering_duration));
return;
}
showCenterTipDialog(R.mipmap.icon_dialog_success,getString(R.string.start_watering));//
String status = mDeviceEntity.getStatus();
if(status.equals("1")){
status = "0";
}else{
status = "1";
}
mPresenter.switchDeviceWork(mDeviceEntity.getId(),status,
mCustomDuration == 0 ? convertToMinutes(mTimeList.get(mAdapter.getmSelPostion()))
: mCustomDuration);
handleDeviceSwitch();
break;
}
}
@@ -256,6 +325,50 @@ public class DeviceControlActivity extends BaseActivity<DeviceControlLayoutBindi
/**
* 处理设备开关操作
*/
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);
@@ -287,9 +400,38 @@ public class DeviceControlActivity extends BaseActivity<DeviceControlLayoutBindi
hideDialogLoading();
viewBinding.imgBatStatus.setImageResource(PowerIconManage.getInstance().
getPowerVerIcon(Integer.parseInt(bean.getPowerLevel())));
mRemoteDeviceEntity = bean;
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;
@@ -301,13 +443,128 @@ public class DeviceControlActivity extends BaseActivity<DeviceControlLayoutBindi
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
public void logOut(BaseBean bean) {
}
@Override
public void addDeviceSuccess(BaseBean bean) {
public void addDeviceSuccess(WaterDeviceEntity bean) {
}
@@ -323,8 +580,11 @@ public class DeviceControlActivity extends BaseActivity<DeviceControlLayoutBindi
}
@Override
public void turnOnOffDeviceSuccess(BaseBean bean) {
public void queryDeviceBindStatusSuccess(WaterDeviceEntity bean) {
}
}

View File

@@ -19,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());
@@ -27,7 +30,14 @@ 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)
.statusBarDarkFont(ThemeManager.isAppThemeLight(mContext)) // 白色状态栏图标
.navigationBarColor(R.color.mainBackgroundColor)
@@ -69,7 +79,7 @@ public class DeviceInfoActivity extends BaseActivity<DeviceInfoLayoutBinding, De
}
@Override
public void addDeviceSuccess(BaseBean bean) {
public void addDeviceSuccess(WaterDeviceEntity bean) {
}
@@ -89,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,6 +8,7 @@ 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;
@@ -23,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());
@@ -31,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) // 设置状态栏字体为黑色
@@ -60,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;
}
}
@@ -73,14 +89,16 @@ 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);
@@ -99,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
@@ -119,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

@@ -107,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:
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,200);
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:
@@ -205,7 +223,7 @@ public class DeviceSettingsActivity extends BaseActivity<DeviceSettingsLayoutBin
}
@Override
public void addDeviceSuccess(BaseBean bean) {
public void addDeviceSuccess(WaterDeviceEntity bean) {
}
@@ -219,7 +237,17 @@ public class DeviceSettingsActivity extends BaseActivity<DeviceSettingsLayoutBin
@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,20 +1,21 @@
package com.ckkj.water.device;
import static android.view.View.GONE;
import static android.view.View.VISIBLE;
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.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 androidx.core.app.ActivityCompat;
import android.widget.EditText;
import android.widget.ImageView;
import com.ckkj.water.ConstantUtil;
import com.ckkj.water.R;
@@ -26,6 +27,8 @@ 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;
@@ -37,6 +40,7 @@ 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;
/**
@@ -45,18 +49,39 @@ import java.util.Set;
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() {
@@ -66,27 +91,14 @@ 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);
}
@Override
protected void onDestroy() {
super.onDestroy();
if (WITCH_FROM_CODE == 100 && espProvisionManager != null) {
cancelBleConnectTask();
if (WITCH_FROM_CODE == 100 && espProvisionManager != null && !keepBleConnectionForProvision) {
espProvisionManager.disconnect();
espProvisionManager.setCallback(null);
}
@@ -115,10 +127,35 @@ public class SelectWifiActivity extends BaseActivity<DeviceResetWifiBinding, Dev
initWifiList();
if (WITCH_FROM_CODE == 100) {
initEspProvision();
connectBleDevice();
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(mContext);
viewBinding.rvWifiList.setAdapter(wifiListAdapter);
@@ -135,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) {
@@ -154,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;
@@ -168,45 +206,85 @@ 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){
provisionWifi();
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 provisionWifi() {
if (espProvisionManager == null) {
ToastUtil.showShort(mContext, "设备连接未初始化");
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) {
connectBleDevice();
scheduleBleConnect();
}
ToastUtil.showShort(mContext, "设备连接中,请稍后再试");
ToastUtil.showShort(mContext, getString(R.string.device_connecting_please_wait));
return;
}
showProgressLoadingDialog(0);
espProvisionManager.provisionWifi(mWifiName, viewBinding.etInputPsd.getText().toString());
// goTo(mContext,DeviceConnectActivity.class,null);
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");
}
@@ -214,7 +292,12 @@ public class SelectWifiActivity extends BaseActivity<DeviceResetWifiBinding, Dev
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
@@ -226,7 +309,7 @@ public class SelectWifiActivity extends BaseActivity<DeviceResetWifiBinding, Dev
@Override
public void onSuccess(String deviceName, String deviceType) {
Log.i("TEST","deviceName" + deviceName + "连接成功");
ToastUtil.showShort(mContext, deviceName + "连接成功");
ToastUtil.showShort(mContext, getString(R.string.connection_success));
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
@@ -237,26 +320,33 @@ public class SelectWifiActivity extends BaseActivity<DeviceResetWifiBinding, Dev
@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);
hideDialogLoading();
stopConnectAnimation();
finish();
}
@Override
public void onDisconnected() {
isBleConnecting = false;
isBleConnected = false;
hideDialogLoading();
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
@@ -274,6 +364,13 @@ public class SelectWifiActivity extends BaseActivity<DeviceResetWifiBinding, Dev
/**
* 连接设备
*/
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;
@@ -281,26 +378,78 @@ public class SelectWifiActivity extends BaseActivity<DeviceResetWifiBinding, Dev
if (isBleConnected || isBleConnecting) {
return;
}
espProvisionManager.connect(mBleDeviceEntity.getMacAddress(), mBleDeviceEntity.getDeviceName());
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;
}
private void displayWifiList(List<ScanResult> scanResults) {
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 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);
@@ -319,8 +468,19 @@ 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) {
}
@@ -340,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

@@ -29,14 +29,21 @@ public class DeviceContract {
//手动开启关闭设备
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

@@ -4,9 +4,11 @@ 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;
@@ -19,7 +21,7 @@ public class DeviceImpl implements DeviceContract.DataModel{
@Override
public void getDeviceInfomation(Map<String, String> map, IndexContract.CallBack callBack) {
String deviceID = map.get("id");
String deviceID = map.get("deviceNo");
NetWorkManager.getRequest().getDeviceDetailInfo(NetWorkManager.getToken(), deviceID)
.subscribeOn(Schedulers.io())
.unsubscribeOn(Schedulers.io())
@@ -59,15 +61,15 @@ public class DeviceImpl implements DeviceContract.DataModel{
.subscribeOn(Schedulers.io())
.unsubscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<BaseBean>() {
.subscribe(new Observer<BaseBean<WaterDeviceEntity>>() {
@Override
public void onSubscribe(@NonNull Disposable d) {
}
@Override
public void onNext(@NonNull BaseBean bean) {
public void onNext(@NonNull BaseBean<WaterDeviceEntity> bean) {
if (bean.getCode() == 200) {
callBack.success(bean,0);
callBack.success(bean.getData(),0);
} else {
callBack.fail(bean.getMessage());
}
@@ -132,9 +134,9 @@ public class DeviceImpl implements DeviceContract.DataModel{
* @param callBack
*/
@Override
public void deleteDevice(String devID, IndexContract.CallBack callBack) {
public void deleteDevice(String deviceNo, IndexContract.CallBack callBack) {
try {
NetWorkManager.getRequest().unBindDevice(NetWorkManager.getToken(), devID)
NetWorkManager.getRequest().unBindDevice(NetWorkManager.getToken(), deviceNo)
.subscribeOn(Schedulers.io())
.unsubscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
@@ -205,4 +207,38 @@ public class DeviceImpl implements DeviceContract.DataModel{
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

@@ -3,6 +3,8 @@ 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;
@@ -21,21 +23,24 @@ public class DevicePresenter extends BasePresenter<DeviceContract.DeviceView> {
/**
* 添加设备
* @param mWifiName
* @param mWifiPassword
* @param mBleDeviceEntity
*/
public void addDevice() {
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);
}
@@ -55,11 +60,11 @@ public class DevicePresenter extends BasePresenter<DeviceContract.DeviceView> {
/**
* 获取设备详情信息
* @param deviceID
* @param deviceNo
*/
public void getDeviceDetailInfo(String deviceID) {
public void getDeviceDetailInfo(String deviceNo) {
Map<String,String> map = new HashMap<>();
map.put("id",deviceID);
map.put("deviceNo",deviceNo);
impl.getDeviceInfomation(map, new IndexContract.CallBack<WaterDeviceEntity>() {
@Override
public void success(WaterDeviceEntity bean, int total) {
@@ -84,7 +89,7 @@ public class DevicePresenter extends BasePresenter<DeviceContract.DeviceView> {
public void updateDeviceInfo(WaterDeviceEntity mDeviceEntity) {
try {
JSONObject json = new JSONObject();
json.put("id",mDeviceEntity.getId());
json.put("deviceNo",mDeviceEntity.getDeviceNo());
json.put("deviceName",mDeviceEntity.getDeviceName());
json.put("wifiName",mDeviceEntity.getWifiName());
json.put("wifiPassword",mDeviceEntity.getWifiPassword());
@@ -113,7 +118,7 @@ public class DevicePresenter extends BasePresenter<DeviceContract.DeviceView> {
* @param deviceEntity
*/
public void unBindDevice(WaterDeviceEntity deviceEntity) {
impl.deleteDevice(deviceEntity.getId(), new IndexContract.CallBack<BaseBean>() {
impl.deleteDevice(deviceEntity.getDeviceNo(), new IndexContract.CallBack<BaseBean>() {
@Override
public void success(BaseBean bean, int total) {
if (DevicePresenter.this.getView() != null) {
@@ -132,14 +137,14 @@ public class DevicePresenter extends BasePresenter<DeviceContract.DeviceView> {
/**
* 开启/关闭浇水
* @param id
* @param deviceEntity
* @param status
* @param duration
*/
public void switchDeviceWork(String id, String status, int duration) {
public void switchDeviceWork(WaterDeviceEntity deviceEntity, String status, int duration) {
try {
JSONObject json = new JSONObject();
json.put("id",id);
json.put("deviceNo",deviceEntity.getDeviceNo());
json.put("workStatus",status);
// json.put("startTime","09:50");
json.put("durationMin",duration + "");
@@ -147,7 +152,7 @@ public class DevicePresenter extends BasePresenter<DeviceContract.DeviceView> {
@Override
public void success(BaseBean bean,int total) {
if(DevicePresenter.this.getView() != null){
DevicePresenter.this.getView().turnOnOffDeviceSuccess(bean);
DevicePresenter.this.getView().turnOnOffDeviceSuccess(bean,status);
}
}
@@ -162,4 +167,60 @@ public class DevicePresenter extends BasePresenter<DeviceContract.DeviceView> {
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() {

View File

@@ -36,23 +36,47 @@ public class EspProvisionManager {
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();
}
@@ -68,6 +92,28 @@ public class EspProvisionManager {
}
};
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());
@@ -110,6 +156,10 @@ public class EspProvisionManager {
return provisioning;
}
public int getProvisionProgress() {
return provisionProgress;
}
public void connect(String deviceAddress, String deviceName) {
connect(deviceAddress, deviceName, AppConfig.BLUETOOTH_DEVICE_UUID);
}
@@ -150,64 +200,93 @@ public class EspProvisionManager {
return;
}
String primaryServiceUuid = TextUtils.isEmpty(serviceUuid) ? ProvisionConfig.SERVICE_UUID : serviceUuid;
String displayName = !TextUtils.isEmpty(deviceName) ? deviceName : bluetoothDevice.getName();
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;
ignoreNextDisconnectEvent = espDevice != null;
boolean hadActiveDevice = espDevice != null && (connecting || connected || provisioning);
ignoreNextDisconnectEvent = hadActiveDevice;
disconnectDeviceOnly();
ensureEventBusRegistered();
espDevice = provisionManager.createESPDevice(
ESPConstants.TransportType.TRANSPORT_BLE,
parseSecurityType(securityType)
parseSecurityType(pendingSecurityType)
);
espDevice.setBluetoothDevice(bluetoothDevice);
espDevice.setPrimaryServiceUuid(primaryServiceUuid);
espDevice.setBluetoothDevice(pendingBluetoothDevice);
espDevice.setPrimaryServiceUuid(pendingServiceUuid);
espDevice.setDeviceName(displayName);
espDevice.setProofOfPossession(proofOfPossession == null ? "" : proofOfPossession);
espDevice.setUserName(userName == null ? "" : userName);
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(bluetoothDevice, primaryServiceUuid);
espDevice.connectBLEDevice(pendingBluetoothDevice, pendingServiceUuid);
}
public void scanDeviceWifiList() {
if (!checkConnected()) {
notifyWifiListFailed("设备未连接");
return;
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;
}
espDevice.scanNetworks(new WiFiScanListener() {
@Override
public void onWifiListReceived(ArrayList<WiFiAccessPoint> wifiList) {
Set<String> wifiNames = new LinkedHashSet<>();
if (wifiList != null) {
for (WiFiAccessPoint accessPoint : wifiList) {
if (accessPoint != null && !TextUtils.isEmpty(accessPoint.getWifiName())) {
wifiNames.add(accessPoint.getWifiName());
}
}
}
notifyWifiListReceived(wifiNames.toArray(new String[0]));
private void clearPendingConnect() {
pendingBluetoothDevice = null;
pendingDeviceName = null;
pendingServiceUuid = null;
pendingProofOfPossession = null;
pendingUserName = null;
pendingSecurityType = 0;
connectRetryCount = 0;
connectStartTime = 0;
}
@Override
public void onWiFiScanFailed(Exception e) {
notifyWifiListFailed(getErrorMessage(e, "获取设备 WiFi 列表失败"));
}
});
}
public void provision(String ssid, String password) {
provisionWifi(ssid, password);
}
public void provisionWifi(String ssid, String password) {
if (!checkConnected()) {
@@ -221,10 +300,13 @@ public class EspProvisionManager {
}
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) {
@@ -233,7 +315,7 @@ public class EspProvisionManager {
@Override
public void wifiConfigSent() {
notifyProvisioning(30);
advanceProvisionProgress(30, 59);
}
@Override
@@ -244,7 +326,7 @@ public class EspProvisionManager {
@Override
public void wifiConfigApplied() {
notifyProvisioning(60);
advanceProvisionProgress(60, MAX_AUTO_PROGRESS);
}
@Override
@@ -269,27 +351,40 @@ public class EspProvisionManager {
});
}
/**
* 通过蓝牙请求 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();
resetState();
lastDisconnectTime = System.currentTimeMillis();
resetState(true);
clearPendingConnect();
if (shouldNotify) {
notifyDisconnected();
}
}
public void release() {
disconnect();
callback = null;
mainHandler.removeCallbacksAndMessages(null);
if (eventBusRegistered) {
EventBus.getDefault().unregister(this);
eventBusRegistered = false;
}
if (instance == this) {
instance = null;
}
}
@Subscribe(threadMode = ThreadMode.MAIN)
public void onDeviceConnectionEvent(DeviceConnectionEvent event) {
@@ -300,8 +395,10 @@ public class EspProvisionManager {
switch (event.getEventType()) {
case ESPConstants.EVENT_DEVICE_CONNECTED:
mainHandler.removeCallbacks(connectionTimeoutTask);
mainHandler.removeCallbacks(connectRetryTask);
connecting = false;
connected = true;
connectRetryCount = 0;
notifyConnected();
break;
@@ -312,7 +409,13 @@ public class EspProvisionManager {
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, "设备通信失败");
@@ -327,14 +430,27 @@ public class EspProvisionManager {
mainHandler.removeCallbacks(connectionTimeoutTask);
mainHandler.removeCallbacks(provisionTimeoutTask);
boolean shouldNotify = connected || connecting || provisioning;
resetState();
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 (!expectDisconnected) {
if (!expectedDisconnect) {
notifyDisconnected();
}
expectDisconnected = false; // 重置标志
}
break;
@@ -363,14 +479,20 @@ public class EspProvisionManager {
}
}
private void resetState() {
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 保持不变,用于断开回调判断
expectDisconnected = false;
if (clearDevice) {
espDevice = null;
}
}
private ESPConstants.SecurityType parseSecurityType(int securityType) {
@@ -385,6 +507,7 @@ public class EspProvisionManager {
private void finishProvisionSuccess() {
mainHandler.removeCallbacks(provisionTimeoutTask);
stopProvisionProgressTask();
provisioning = false;
expectDisconnected = true; // 标记为预期断开
notifyProvisioning(100);
@@ -393,10 +516,27 @@ public class EspProvisionManager {
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 密码错误";
@@ -447,11 +587,13 @@ public class EspProvisionManager {
}
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(progress);
callback.onProvisioning(provisionProgress);
}
}
});
@@ -490,27 +632,6 @@ public class EspProvisionManager {
});
}
private void notifyWifiListReceived(final String[] wifiList) {
runOnMainThread(new Runnable() {
@Override
public void run() {
if (callback != null) {
callback.onWifiListReceived(wifiList);
}
}
});
}
private void notifyWifiListFailed(final String message) {
runOnMainThread(new Runnable() {
@Override
public void run() {
if (callback != null) {
callback.onWifiListFailed(message);
}
}
});
}
private void notifyProvisioningRejected() {
runOnMainThread(new Runnable() {

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;
@@ -95,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();
});
}

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

@@ -15,9 +15,7 @@ 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;

View File

@@ -17,7 +17,11 @@ 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
@@ -47,10 +51,79 @@ public class StatisticFragment extends BaseFragment<WaterCountFragmentLayoutBind
viewBinding.tvThisMonthValue.setText(entity.getMonCount()+"");
viewBinding.tvPlanValue.setText(entity.getSchedule()+"");
viewBinding.tvManuallyValue.setText(entity.getManualNum()+"");
viewBinding.tvTotalDurationValue.setText(entity.getAllTime()+"");
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());

View File

@@ -99,8 +99,11 @@ public class TabHistoryFragment extends BaseFragment<TabHistoryFragmentLayoutBin
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() {
@@ -182,13 +185,14 @@ public class TabHistoryFragment extends BaseFragment<TabHistoryFragmentLayoutBin
public void callBack(boolean mSelManual, boolean mSelAuto) {
if (mSelManual) {
mFilterType = 1;
}
if(mSelAuto){
} else if (mSelAuto) {
mFilterType = 0;
} else {
mFilterType = -1;
}
getWaterHistoryList();
}
}));
}, mFilterType));
typePopupView.show();
break;

View File

@@ -34,7 +34,9 @@ public class WateringHistoryAdapter extends BaseQuickAdapter<WateringRecord, Bas
helper.setText(R.id.tv_plan_duration,mContext.getString(R.string.device_work_times_title)
+ ":" + 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

@@ -10,8 +10,8 @@ import lombok.NoArgsConstructor;
* @date 2026/5/15
* @description 浇水历史记录
*/
@Data
@NoArgsConstructor
@Data
public class WateringRecord implements Serializable {
/**
@@ -45,9 +45,21 @@ public class WateringRecord implements Serializable {
private String userId;
private String deviceNo;
private String deviceId;
private int scheduleId;
private String scheduleId;
private String durationMin;
private Object zones;
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,6 +1,5 @@
package com.ckkj.water.history.mvp;
import com.ckkj.water.base.entity.MineUserInfoBean;
import com.ckkj.water.history.entity.WaterStatisticsEntity;
import com.ckkj.water.history.entity.WateringRecord;
import com.ckkj.water.network.BaseBean;

View File

@@ -28,19 +28,19 @@ public class HistoryPresenter extends BasePresenter<HistoryContract.HistoryView>
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("beginTime",mFilterStartTime);
map.put("param[beginTime]", mFilterStartTime);
map.put("params[beginTime]", mFilterStartTime);
}
if(!TextUtils.isEmpty(mFilterStartTime)){
// map.put("endTime",mFilterEndTime);
map.put("param[endTime]", mFilterEndTime);
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) {

View File

@@ -1,23 +1,30 @@
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.os.Handler;
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.AddDeviceActivity_copy;
import com.ckkj.water.device.DeviceControlActivity;
import com.ckkj.water.history.entity.WateringRecord;
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.WaterDeviceEntity;
import com.ckkj.water.index.mvp.IndexContract;
@@ -25,13 +32,15 @@ import com.ckkj.water.index.mvp.IndexImpl;
import com.ckkj.water.index.mvp.IndexPresenter;
import com.ckkj.water.network.BaseBean;
import com.ckkj.water.permission.PermissionActivity;
import com.ckkj.water.plan.entity.WaterPlanWeekEntity;
import com.ckkj.water.utils.show.ToastUtil;
import com.maning.mlkitscanner.scan.MNScanManager;
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;
@@ -44,6 +53,15 @@ public class IndexFragment extends BaseFragment<IndexFragmentLayoutBinding, Inde
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) {
}
@@ -99,6 +117,7 @@ public class IndexFragment extends BaseFragment<IndexFragmentLayoutBinding, Inde
switch (v.getId()){
case R.id.img_scan:
if(checkBluetoothPermissions()){
//检测有无相机权限
String readPermission = Manifest.permission.CAMERA;
if(!hasRecordPermission(readPermission)){
@@ -109,15 +128,18 @@ public class IndexFragment extends BaseFragment<IndexFragmentLayoutBinding, Inde
}else{
scanQrcode();
}
}else{
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);
if(checkBluetoothPermissions()){
goTo(mContext, AddDeviceActivity.class,null);
}else{
goTo(mContext, AddDeviceActivity_copy.class,null);
goTo(mContext, PermissionActivity.class,null);
}
break;
@@ -136,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;
}
}
@@ -198,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() {
@@ -218,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

@@ -29,15 +29,34 @@ public class DeviceAdapter extends BaseQuickAdapter<WaterDeviceEntity, BaseViewH
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,item.getWorkStatus().equals("0") ?
mContext.getString(R.string.device_status_not_working) :
mContext.getString(R.string.device_status_working));
holder.setTextColor(R.id.tv_device_status,item.getWorkStatus().equals("0") ?
mContext.getResources().getColor(R.color.color_999999) :
mContext.getResources().getColor(R.color.color_24B326));
viewStatus.setBackground(item.getWorkStatus().equals("0") ?
mContext.getResources().getDrawable(R.drawable.shape_status_dot_999999)
: mContext.getResources().getDrawable(R.drawable.shape_status_dot_green));
//设备联网在线
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

@@ -36,7 +36,7 @@ public class WaterDeviceEntity implements Serializable {
private String status;
private String workStatus;
private String powerLevel;
private Object powerLevelUpdatatime;
private String powerLevelUpdatatime;
private String wifiName;
private String wifiPassword;
private String deviceEm;
@@ -45,9 +45,14 @@ public class WaterDeviceEntity implements Serializable {
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;
@NoArgsConstructor
@Data
@NoArgsConstructor
public static class DeviceListBean implements Serializable{
private String id;
private String deviceNo;
@@ -65,5 +70,15 @@ public class WaterDeviceEntity implements Serializable {
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

@@ -3,6 +3,8 @@ package com.ckkj.water.index.mvp;
import com.ckkj.water.base.IView;
import com.ckkj.water.index.entity.WaterDeviceEntity;
import org.json.JSONObject;
import java.util.List;
import java.util.Map;
@@ -21,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<WaterDeviceEntity> list, int total);
//查询二维码当前设备绑定状态
void queryDeviceBindStatusSuccess(WaterDeviceEntity entity);
}
}

View File

@@ -4,6 +4,8 @@ import com.ckkj.water.index.entity.WaterDeviceEntity;
import com.ckkj.water.network.BaseBean;
import com.ckkj.water.network.NetWorkManager;
import org.json.JSONObject;
import java.util.List;
import java.util.Map;
@@ -49,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

@@ -2,6 +2,10 @@ package com.ckkj.water.index.mvp;
import com.ckkj.water.base.BasePresenter;
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;
@@ -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;
@@ -23,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());
@@ -50,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) {
@@ -111,11 +121,39 @@ public class ForgetPasswordActivity extends BaseActivity<RegisterLayoutBinding,
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));
@@ -153,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

View File

@@ -10,18 +10,23 @@ 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;
@@ -49,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
@@ -80,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) {
@@ -104,7 +113,10 @@ public class LoginActivity extends BaseActivity<LoginLayoutBinding, LoginPresent
content,
userAgreementText,
() -> {
ToastUtil.showShort(mContext, "用户协议");
// 跳转用户协议
Bundle bundle = new Bundle();
bundle.putInt("from_requse_code", WebviewUserAgreement.AGREEMENT_CODE);
goToWihoutNoPresent(mContext, WebviewUserAgreement.class,bundle);
}
);
@@ -113,7 +125,10 @@ public class LoginActivity extends BaseActivity<LoginLayoutBinding, LoginPresent
content,
privacyPolicyText,
() -> {
ToastUtil.showShort(mContext, "隐私政策");
// 跳转隐私政策
Bundle bundleYS = new Bundle();
bundleYS.putInt("from_requse_code",WebviewUserAgreement.PRIVACY_CODE);
goToWihoutNoPresent(mContext, WebviewUserAgreement.class,bundleYS);
}
);
@@ -169,6 +184,21 @@ public class LoginActivity extends BaseActivity<LoginLayoutBinding, LoginPresent
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;
@@ -254,15 +284,6 @@ public class LoginActivity extends BaseActivity<LoginLayoutBinding, LoginPresent
goTo(mContext, ForgetPasswordActivity.class,null);
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_login:
if (TextUtils.isEmpty(viewBinding.etAccount.getText().toString())) {
ToastUtil.showShort(mContext, getString(R.string.login_error_phone_empty));
@@ -305,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));
@@ -329,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) {
@@ -337,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

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.FastClickUtils;
import com.ckkj.water.utils.manager.ThemeManager;
import com.ckkj.water.utils.number.PhoneNumberUtils;
import com.ckkj.water.utils.show.ToastUtil;
@@ -22,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());
@@ -48,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) {
@@ -61,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;
@@ -72,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;
@@ -110,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));
@@ -135,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

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);
}
});
}

View File

@@ -22,7 +22,6 @@ public class LoginContract {
public interface DataModel{
//手机验证码登录
void register(JSONObject json, CallBack callBack);
//获取手机验证码
void getPhoneCode(Map<String,Object> map, CallBack callBack);
//手机验证码登录
@@ -31,6 +30,10 @@ public class LoginContract {
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{

View File

@@ -105,6 +105,88 @@ 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
@@ -226,4 +308,6 @@ public class LoginImpl implements LoginContract.DataModel {
e.printStackTrace();
}
}
}

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,7 +312,23 @@ 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
@@ -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;
@@ -122,4 +123,24 @@ public class AppThemActivity extends BaseActivity<AppThemeChangeLayoutBinding, M
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;
@@ -151,4 +151,24 @@ public class ChangePhoneActivity extends BaseActivity<ChangePhoneActivityBinding
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,22 +1,21 @@
package com.ckkj.water.mine;
import static android.view.View.INVISIBLE;
import static android.view.View.VISIBLE;
import android.app.Activity;
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.main.entity.CheckVersionEntity;
import com.ckkj.water.mine.entity.MineUserInfoBean;
import com.ckkj.water.databinding.MineFragmentLayoutBinding;
import com.ckkj.water.login.LoginActivity;
import com.ckkj.water.main.entity.CheckVersionEntity;
import com.ckkj.water.mine.entity.MemberComboEntity;
import com.ckkj.water.mine.mvp.MineContract;
import com.ckkj.water.mine.mvp.MineImpl;
import com.ckkj.water.mine.mvp.MinePresenter;
@@ -26,16 +25,11 @@ 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;
import de.greenrobot.event.EventBus;
/**
* @author fengxiaoyang
* @date 2026/5/16
@@ -52,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();
}
@@ -70,6 +65,7 @@ public class MineCenterFragment extends BaseFragment<MineFragmentLayoutBinding,
setClick(viewBinding.linearPsdManage);
setClick(viewBinding.linearTheme);
setClick(viewBinding.btnDelete);
setClick(viewBinding.includedTitle.imgSetting);
}
private void setClick(View view) {
@@ -78,6 +74,11 @@ public class MineCenterFragment extends BaseFragment<MineFragmentLayoutBinding,
public void onClick(View v){
switch (v.getId()){
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);
@@ -152,6 +153,13 @@ public class MineCenterFragment extends BaseFragment<MineFragmentLayoutBinding,
}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);
}
}
/**
@@ -165,6 +173,26 @@ public class MineCenterFragment extends BaseFragment<MineFragmentLayoutBinding,
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) {

View File

@@ -1,284 +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) {
}
@Override
public void updateUserInfoSuccess(BaseBean bean) {
}
@Override
public void updateUserPasswordSuccess(BaseBean bean) {
}
@Override
public void logOutSuccess(BaseBean bean) {
}
}

View File

@@ -13,7 +13,8 @@ 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;
@@ -22,6 +23,7 @@ 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;
@@ -56,6 +58,13 @@ public class MineInfomationActivity extends BaseActivity<MineInformationLayoutBi
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{
@@ -90,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) {
@@ -98,16 +111,18 @@ 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;
}
}
@@ -115,12 +130,13 @@ public class MineInfomationActivity extends BaseActivity<MineInformationLayoutBi
break;
case R.id.rl_nickname:
showEditDialog("修改昵称",
"请输入昵称",
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
@@ -134,7 +150,7 @@ public class MineInfomationActivity extends BaseActivity<MineInformationLayoutBi
@Override
public void onConfirmClisk(String content) {
showLoadingDialog();
mPresenter.updateUserInfo(content);
mPresenter.updateUserInfo(content,null);
mUserBean.getUser().setNickName(content);
viewBinding.tvNicknameValue.setText(content);
}
@@ -190,6 +206,50 @@ public class MineInfomationActivity extends BaseActivity<MineInformationLayoutBi
}
@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() {
@@ -202,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));
}
}
}

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.PasswordManLayoutBinding;
import com.ckkj.water.login.ForgetPasswordActivity;
import com.ckkj.water.mine.mvp.MineContract;
@@ -101,4 +102,24 @@ public class PsdManageActivity extends BaseActivity<PasswordManLayoutBinding, Mi
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,12 +1,17 @@
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;
@@ -24,6 +29,10 @@ 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);
@@ -40,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) {
@@ -77,9 +89,45 @@ public class ResetPsdActivity extends BaseActivity<ResetPsdLayoutBinding, MinePr
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
@@ -96,6 +144,26 @@ public class ResetPsdActivity extends BaseActivity<ResetPsdLayoutBinding, MinePr
}
@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());

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();
@@ -221,4 +227,114 @@ public class SettingsActivity extends BaseActivity<ActivitySettingsLayoutBinding
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,14 +50,27 @@ 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);
}
public void onClick(View v) {
@@ -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));
@@ -131,4 +185,16 @@ public class UserLogOffAccountActivity extends BaseActivity<UserLogOffActivityBi
public void logOutSuccess(BaseBean bean) {
}
@Override
public void uploadImageSuccess(MineUserInfoBean bean) {
}
@Override
public void getAppVersionSuccess(CheckVersionEntity bean) {
}
}

View File

@@ -1,4 +1,4 @@
package com.ckkj.water.base.entity;
package com.ckkj.water.mine.entity;
import java.io.Serializable;
import java.util.List;
@@ -26,6 +26,8 @@ public class MineUserInfoBean implements Serializable {
private UserBean user;
private List<?> permissions;
private List<?> roles;
private String url;
@NoArgsConstructor
@Data
@@ -64,7 +66,7 @@ public class MineUserInfoBean implements Serializable {
private String email;
private String phonenumber;
private String sex;
private Object avatar;
private String avatar;
private String password;
private String status;
private String loginIp;
@@ -77,5 +79,6 @@ public class MineUserInfoBean implements Serializable {
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;
/**
@@ -33,6 +27,8 @@ public class MineContract {
void updateUserInfo(JSONObject json, CallBack callBack);
//通过旧密码,修改新密码
void updateUserPwdByOld(JSONObject json, CallBack callBack);
//上传图片
void uploadImage(JSONObject json, CallBack callBack);
}
@@ -47,6 +43,14 @@ public class MineContract {
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,15 +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.LoginStateManager;
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;
@@ -17,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
@@ -140,4 +140,76 @@ public class MineImpl implements MineContract.DataModel {
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

@@ -1,22 +1,22 @@
package com.ckkj.water.mine.mvp;
import android.text.Editable;
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.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 com.ckkj.water.utils.dataUtil.SharePreUtil;
import com.ckkj.water.utils.manager.WaterUserInfoManager;
import com.google.gson.Gson;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.File;
import java.util.HashMap;
import java.util.Map;
@@ -58,12 +58,18 @@ public class MinePresenter extends BasePresenter<MineContract.MineView> {
/**
* 修改用户信息
* @param content
* @param nickName
* @param avatar
*/
public void updateUserInfo(String content) {
public void updateUserInfo(String nickName,String avatar) {
try {
JSONObject json = new JSONObject();
json.put("nickName", content);
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) {
@@ -135,4 +141,109 @@ public class MinePresenter extends BasePresenter<MineContract.MineView> {
}
});
}
/**
* 上传图片
* @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;
@@ -83,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;
}
}
/**
* 初始化必要对象和参数
*/
@@ -101,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();
@@ -131,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) //读取超时
@@ -337,7 +389,9 @@ public class NetWorkManager {
public static Map<String, String> getToken() {
Map<String, String> map = new HashMap<>();
try {
if(!TextUtils.isEmpty(AppConfig.USER_TOKEN)){
map.put("Authorization", "Bearer " + AppConfig.USER_TOKEN);
}
map.put("clientId", AppConfig.APP_CLIENT_ID);
map.put("content-language", LanguageManager.getCurrentRequestLanguage());
} catch (Exception e) {

View File

@@ -2,28 +2,29 @@ package com.ckkj.water.network;
import com.ckkj.water.base.entity.MineUserInfoBean;
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.plan.entity.WaterPlanWeekEntity;
import com.ckkj.water.plate.entity.BaziResultBean;
import com.ckkj.water.plate.entity.BaziSaveSuccessEntity;
import com.ckkj.water.plate.entity.PaipanHistoryEntity;
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;
@@ -36,6 +37,16 @@ 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);
@@ -54,20 +65,38 @@ public interface Request {
@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<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/{id}")
Observable<BaseBean<WaterDeviceEntity>> getDeviceDetailInfo(@HeaderMap Map<String, String> headMap, @Path("id") String id);
@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);
@@ -115,8 +144,8 @@ public interface Request {
//删除设备
@DELETE("app/v1/deleteDevice/{ids}")
Observable<BaseBean> unBindDevice(@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")
@@ -134,28 +163,14 @@ public interface Request {
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

@@ -5,16 +5,13 @@ 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;

View File

@@ -19,7 +19,7 @@ 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;
@@ -76,7 +76,7 @@ public class AddWaterPlanActivity extends BaseActivity<AddWaterPlanLayoutBinding
viewBinding.includedTitle.tvTitle.setText(R.string.add_water_plan_title);
viewBinding.tvBound.setVisibility(GONE);
}
mFragmentList.add(new WaterConfigFragment_copy());
mFragmentList.add(new WaterConfigFragment());
mFragmentList.add(new PlanBoundDeviceFragment());
mFragmentList.add(new BindDeviceFragment());
ViewPagerAdapter adapter = new ViewPagerAdapter(mContext, mFragmentList);
@@ -92,7 +92,7 @@ public class AddWaterPlanActivity extends BaseActivity<AddWaterPlanLayoutBinding
// 编辑模式下,延迟传递数据给 WaterConfigFragment等 viewBinding 初始化完成后调用
if (mIsEditMode && mEditEntity != null) {
viewBinding.viewpage.post(() -> {
WaterConfigFragment_copy configFragment = (WaterConfigFragment_copy) mFragmentList.get(0);
WaterConfigFragment configFragment = (WaterConfigFragment) mFragmentList.get(0);
configFragment.setEditEntity(mEditEntity);
PlanBoundDeviceFragment boundDeviceFragment = (PlanBoundDeviceFragment) mFragmentList.get(1);
@@ -137,7 +137,7 @@ public class AddWaterPlanActivity extends BaseActivity<AddWaterPlanLayoutBinding
break;
case R.id.tv_bind:
WaterConfigFragment_copy configFragment = (WaterConfigFragment_copy) mFragmentList.get(0);
WaterConfigFragment configFragment = (WaterConfigFragment) mFragmentList.get(0);
// 检查是否有未保存的数据变更
if (configFragment.hasDataChanged()) {
@@ -221,7 +221,7 @@ public class AddWaterPlanActivity extends BaseActivity<AddWaterPlanLayoutBinding
* 切换到绑定设备页面
*/
private void proceedToBindDevice() {
WaterConfigFragment_copy configFragment = (WaterConfigFragment_copy) mFragmentList.get(0);
WaterConfigFragment configFragment = (WaterConfigFragment) mFragmentList.get(0);
WaterPlanWeekEntity entity = mIsEditMode ? mEditEntity : mNewAddEntity;
if (entity == null) {
entity = configFragment.getRemoteEntity();

View File

@@ -42,10 +42,10 @@ public class BindDeviceFragment extends BaseFragment<PlanBindDeviceLayoutBinding
@Override
public void onItemClick(BaseQuickAdapter adapter, View view, int position) {
mAdapter.toggleSelection(position);
if(mDeviceList.get(position).getStatus().equals("0")){
mDeviceList.get(position).setStatus("1");
if(mDeviceList.get(position).getCheckStatus().equals("0")){
mDeviceList.get(position).setCheckStatus("1");
}else{
mDeviceList.get(position).setStatus("0");
mDeviceList.get(position).setCheckStatus("0");
}
}
});
@@ -71,9 +71,9 @@ public class BindDeviceFragment extends BaseFragment<PlanBindDeviceLayoutBinding
boolean isSelected = false;
List<String> selected = new ArrayList<>();
for(WaterDeviceEntity.DeviceListBean bean : mDeviceList){
if(bean.getStatus().equals("1")){
if(bean.getCheckStatus().equals("1")){
isSelected = true;
selected.add(bean.getId());
selected.add(bean.getDeviceNo());
}
}
if(!isSelected){

View File

@@ -32,12 +32,12 @@ public class PlanBoundDeviceFragment extends BaseFragment<PlanBoundDeviceLayoutB
@Override
public void initData(Bundle state) {
// 初始化适配器,如果有数据则设置
if (mEditEntity != null && mEditEntity.getDeviceIds() != null) {
mAdapter = new PlanBoundDeviceAdapter(mContext, R.layout.plan_bound_device_item, mEditEntity.getDeviceIds());
if (mEditEntity != null && mEditEntity.getDeviceNos() != null) {
mAdapter = new PlanBoundDeviceAdapter(mContext, R.layout.plan_bound_device_item, mEditEntity.getDeviceNos());
viewBinding.rvDevices.setAdapter(mAdapter);
// 根据数据状态显示/隐藏视图
if (mEditEntity.getDeviceIds().isEmpty()) {
if (mEditEntity.getDeviceNos().isEmpty()) {
viewBinding.linearContent.setVisibility(View.GONE);
viewBinding.relNoresult.setVisibility(View.VISIBLE);
} else {
@@ -55,8 +55,11 @@ public class PlanBoundDeviceFragment extends BaseFragment<PlanBoundDeviceLayoutB
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_unbind_device),
getString(R.string.cancel_text),
getString(R.string.confirm_text),
new OnDialogClick() {
@Override
public void onCancelClick() {
@@ -66,7 +69,7 @@ public class PlanBoundDeviceFragment extends BaseFragment<PlanBoundDeviceLayoutB
public void onConfirmClick() {
showLoadingDialog();
mPresenter.planUnbindDevice(mEditEntity.getId(),
mEditEntity.getDeviceIds().get(position).getId(),
mEditEntity.getDeviceNos().get(position).getDeviceNo(),
position);
}
});
@@ -94,20 +97,20 @@ public class PlanBoundDeviceFragment extends BaseFragment<PlanBoundDeviceLayoutB
if (viewBinding == null) {
return;
}
if (mEditEntity == null || mEditEntity.getDeviceIds() == null) {
if (mEditEntity == null || mEditEntity.getDeviceNos() == null) {
viewBinding.linearContent.setVisibility(View.GONE);
viewBinding.relNoresult.setVisibility(View.VISIBLE);
return;
}
if (mEditEntity.getDeviceIds().isEmpty()) {
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.getDeviceIds());
mAdapter.setNewData(mEditEntity.getDeviceNos());
}
}
}
@@ -166,7 +169,7 @@ public class PlanBoundDeviceFragment extends BaseFragment<PlanBoundDeviceLayoutB
hideDialogLoading();
ToastUtil.showShort(mContext, "解绑成功");
mAdapter.notifyItemRemoved(position);
mEditEntity.getDeviceIds().remove(position);
mEditEntity.getDeviceNos().remove(position);
if (mAdapter.getItemCount() != 0) {
viewBinding.relNoresult.setVisibility(View.GONE);
viewBinding.linearContent.setVisibility(View.VISIBLE);

View File

@@ -117,8 +117,11 @@ public class PlanDetailActivity extends BaseActivity<WaterPlanDetailLayoutBindin
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() {
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() {
}
@@ -153,6 +156,7 @@ public class PlanDetailActivity extends BaseActivity<WaterPlanDetailLayoutBindin
// 开启任务,调用接口后再更新 Switch
mPresenter.updatePlanStatus(mDetailEntity, "1");
}
break;
}
}
@@ -170,8 +174,10 @@ public class PlanDetailActivity extends BaseActivity<WaterPlanDetailLayoutBindin
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<>();
@@ -200,7 +206,7 @@ public class PlanDetailActivity extends BaseActivity<WaterPlanDetailLayoutBindin
}
//设备显示
if(deviceAdapter != null){
deviceAdapter.setNewData(entity.getDeviceIds());
deviceAdapter.setNewData(entity.getDeviceNos());
if(deviceAdapter.getItemCount() == 0){
viewBinding.rvBindDevices.setVisibility(View.GONE);
viewBinding.tvNoDevice.setVisibility(View.VISIBLE);
@@ -243,10 +249,12 @@ public class PlanDetailActivity extends BaseActivity<WaterPlanDetailLayoutBindin
hideDialogLoading();
mDetailEntity.setStatus(status);
if(status.equals("1")){
showCenterTipDialog(R.mipmap.icon_dialog_success,"任务已开启");
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));
}
}

View File

@@ -5,6 +5,9 @@ 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;
@@ -13,55 +16,236 @@ 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.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.DetailsBean> mConfigList = new ArrayList<>();
//用户本地操作排程时的数据
private WaterPlanWeekEntity mConfigEntity;
//排程接口新增成功之后,接口返回的该排程在远端的数据信息
private WaterPlanWeekEntity mRemoteConfigEntity;
private WaterPlanWeekAdapter mWeekAdapter;
private String mPlanName = "";
public static boolean isConfigSave;
//本地新增排程时的实体
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) {
mConfigEntity = new WaterPlanWeekEntity();
// 设置菜单创建器。
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);
}
mConfigEntity.setDetails(list);
mWeekAdapter = new WaterPlanWeekAdapter(mContext,R.layout.plan_week_config_item, mConfigEntity.getDetails());
viewBinding.rvWeekConfig.setAdapter(mWeekAdapter);
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.imgAdd);
setClick(viewBinding.switchButton);
//头部 周一~周日
mWeekAdapter.setOnItemClickListener(new BaseQuickAdapter.OnItemClickListener() {
@Override
public void onItemClick(BaseQuickAdapter adapter, View view, int position) {
mWeekAdapter.setSelPos(position);
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;
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) {}
@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.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:
// 防止快速点击
if (!FastClickUtils.onclickTimes()) {
return;
}
// 如果已经保存过mRemoteEntity 不为空),则走更新逻辑;否则走新增逻辑
if (mRemoteEntity != null) {
updateConfig();
} else {
validateAndSave();
}
break;
}
}
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 从详情页传来的排程数据
@@ -72,18 +256,22 @@ public class WaterConfigFragment extends BaseFragment<WaterConfigFragmentLayoutB
}
mIsEditMode = true;
// 深拷贝数据到 mConfigEntity用于本地编辑
mConfigEntity = cloneEntity(entity);
mLocalEntity = cloneEntity(entity);
// 保存远程原始数据,用于后续变化检测
mRemoteConfigEntity = entity;
isConfigSave = true;
mRemoteEntity = entity;
isConfigSubmitted = true;
// 初始化 UI
viewBinding.etPlanName.setText(entity.getName());
mPlanName = entity.getName();
viewBinding.editPlanName.setText(entity.getName());
// 更新周配置列表的显示,使用 mConfigEntity.getDetails() 保证数据一致
if (mConfigEntity.getDetails() != null) {
mWeekAdapter.setNewData(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());
}
}
}
@@ -103,12 +291,18 @@ public class WaterConfigFragment extends BaseFragment<WaterConfigFragmentLayoutB
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());
newBean.setStartTime(ZYTimeUtils.formatHHmm(bean.getStartTime()));
newBean.setDurationMin(bean.getDurationMin());
detailsList.add(newBean);
}
target.setDetails(detailsList);
@@ -117,103 +311,283 @@ public class WaterConfigFragment extends BaseFragment<WaterConfigFragmentLayoutB
return target;
}
private void initListener() {
setClick(viewBinding.tvCommit);
mWeekAdapter.setOnItemChildClickListener(new BaseQuickAdapter.OnItemChildClickListener() {
@Override
public void onItemChildClick(BaseQuickAdapter adapter, View view, int position) {
switch (view.getId()){
case R.id.linear_week://选中
case R.id.checkbox:
if(mConfigEntity.getDetails().get(position).getStatus().equals("1")){
mConfigEntity.getDetails().get(position).setStatus("0");
}else{
mConfigEntity.getDetails().get(position).setStatus("1");
/**
* 校验配置
* @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;
}
mWeekAdapter.notifyItemChanged(position);
break;
case R.id.tv_select_time:
selectStartTime(position);
break;
case R.id.tv_plan_duration:
inputDuration(position);
// 检查七天的所有时间配置是否全部为空
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;
}
viewBinding.etPlanName.addTextChangedListener(new TextWatcher() {
/**
* 校验配置并保存(新增)
* @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 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(!TextUtils.isEmpty(s.toString())){
mPlanName = s.toString();
mConfigEntity.setName(s.toString());
}
}
});
}
public void onClick(View v){
switch (v.getId()){
case R.id.tv_commit:
commitConfig();
break;
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();
}
public void commitConfig(){
if (!checkConfigFinish()) {
return;
}
// mRemoteConfigEntity 为空,说明是新增场景
if (mRemoteConfigEntity == null) {
mPresenter.saveConfig(mConfigEntity);
return;
}
// mRemoteConfigEntity 不为空,说明是更新场景
if (isConfigChanged()) {
// TODO: 触发更新接口,调用 mPresenter.updateConfig(mConfigEntity)
mPresenter.updateConfig(mConfigEntity);
} else {
ToastUtil.showShort(mContext, "配置没有变化,无需保存");
}
}
/**
* 输入浇水时间
* @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),
mConfigEntity.getDetails().get(position).getDurationMin() == 0 ?
"" : mConfigEntity.getDetails().get(position).getDurationMin() + "",
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() {
}
public void onCancelClick() {}
@Override
public void onConfirmClisk() {
}
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;
}
mConfigEntity.getDetails().get(position).setDurationMin(Integer.parseInt(content));
mWeekAdapter.notifyItemChanged(position);
timeData.setDurationMin(Integer.parseInt(content));
mTimeAdapter.notifyItemChanged(position);
}
@Override
@@ -223,138 +597,113 @@ public class WaterConfigFragment extends BaseFragment<WaterConfigFragmentLayoutB
});
}
private void selectStartTime(int position) {
boolean times[] = {false, false, false, true, true, false};
//时间选择器
TimePickerView pvTime = new TimePickerBuilder(mContext, new OnTimeSelectListener() {
@Override
public void onTimeSelect(Date date, View v) {
//用于提交接口
mConfigEntity.getDetails().get(position).setStartTime(ZYTimeUtils.getStrTimeData_H_M(date));
mWeekAdapter.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))
.build();
pvTime.show();
}
private void setClick(View view) {
view.setOnClickListener(this::onClick);
}
/**
* 比较本地配置和远程配置是否有变化
* @return true 表示有变化false 表示无变化
* 侧滑相关
*/
public boolean isConfigChanged() {
if (mRemoteConfigEntity == null || mRemoteConfigEntity.getDetails() == null) {
return true;
}
// 比对排程名称
if (!equalsString(mConfigEntity.getName(), mRemoteConfigEntity.getName())) {
return true;
}
List<WaterPlanWeekEntity.DetailsBean> localDetails = mConfigEntity.getDetails();
List<WaterPlanWeekEntity.DetailsBean> remoteDetails = mRemoteConfigEntity.getDetails();
for (int i = 0; i < localDetails.size(); i++) {
WaterPlanWeekEntity.DetailsBean local = localDetails.get(i);
WaterPlanWeekEntity.DetailsBean remote = remoteDetails.get(i);
// 勾选状态下对比状态、时间、时长
if ("1".equals(local.getStatus())) {
if (!equalsString(local.getStatus(), remote.getStatus())
|| !equalsString(local.getStartTime(), ZYTimeUtils.formatHHmm(remote.getStartTime()))
|| local.getDurationMin() != remote.getDurationMin()) {
return true;
}
} else {
// 未勾选状态下只对比勾选状态,不关心时间/时长
if (!equalsString(local.getStatus(), remote.getStatus())) {
return true;
}
}
}
return false;
// 创建菜单:
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右侧添加一个菜单。
}
};
private boolean equalsString(String s1, String s2) {
if (s1 == null && s2 == null) return true;
if (s1 == null || s2 == null) return false;
return s1.equals(s2);
// 菜单点击监听。
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);
}
}
}
}
};
/**
* 检查配置信息是否完成
* @return
* 新增
* @param entity
*/
public boolean checkConfigFinish() {
if(TextUtils.isEmpty(viewBinding.etPlanName.getText().toString())){
ToastUtil.showShort(mContext,getString(R.string.plan_name_text_empty_hint));
return false;
}
List<WaterPlanWeekEntity.DetailsBean> list = mConfigEntity.getDetails();
//是否勾选了排程日期
boolean isSelectOne = false;
if(list != null){
for(WaterPlanWeekEntity.DetailsBean bean : list){
if(bean.getStatus().equals("1")){
isSelectOne = true;
}
}
}
if(!isSelectOne){
ToastUtil.showShort(mContext,getString(R.string.plan_week_empty_hint));
return false;
}
//是否配置了排程日期的时间
boolean isPlanConfig = false;
for(WaterPlanWeekEntity.DetailsBean bean : list){
if(bean.getStatus().equals("1")){
if((TextUtils.isEmpty(bean.getStartTime()) ||
bean.getDurationMin() == 0)){
ToastUtil.showShort(mContext,"请完成" + bean.getWeekName() + "的时间配置");
return false;
}
}
}
return true;
}
@Override
public void getWaterConfigListSuccess(List<WaterPlanWeekEntity> list,int total) {
}
@Override
public void saveConfigSuccess(WaterPlanWeekEntity entity) {
ToastUtil.showShort(mContext, "排程新增成功");
isConfigSave = true;
ToastUtil.showShort(mContext, getString(R.string.schedule_add_success));
isConfigSubmitted = true;
// 把接口返回的 ID 设置到 mConfigEntity便于后续更新操作
mConfigEntity.setId(entity.getId());
mLocalEntity.setId(entity.getId());
// 把 details 中每个 bean 的 id 也设置到 mConfigEntity便于后续更新操作
if (entity.getDetails() != null && mConfigEntity.getDetails() != null) {
for (int i = 0; i < entity.getDetails().size() && i < mConfigEntity.getDetails().size(); i++) {
mConfigEntity.getDetails().get(i).setId(entity.getDetails().get(i).getId());
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());
}
}
//接口请求之后返回的数据,方便后面做对比
mRemoteConfigEntity = entity;
mRemoteEntity = entity;
if (getActivity() instanceof AddWaterPlanActivity) {
((AddWaterPlanActivity) getActivity()).onConfigSaved(entity);
}
}
/**
* 更新排程成功
* 更新
* @param entity
*/
@Override
public void updateConfigSuccess(WaterPlanWeekEntity entity) {
ToastUtil.showShort(mContext, "排程更新成功");
mRemoteConfigEntity = 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());
}
@Override
public void onNetChange(int netModel) {
}
@Override
public void showError(String message) {
}
@Override
public void logOut(BaseBean bean) {
}
@Override
public void getWaterConfigListSuccess(List<WaterPlanWeekEntity> list, int total) {
}
@Override
@@ -388,25 +737,4 @@ public class WaterConfigFragment extends BaseFragment<WaterConfigFragmentLayoutB
}
@Override
public WaterPlanPresenter createPresenter() {
return new WaterPlanPresenter(new WaterPlanImpl());
}
@Override
public void onNetChange(int netModel) {
}
@Override
public void showError(String message) {
}
@Override
public void logOut(BaseBean bean) {
}
}

View File

@@ -1,715 +0,0 @@
package com.ckkj.water.plan;
import android.os.Bundle;
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.WaterPlanTimeDataAdapter;
import com.ckkj.water.plan.adapter.WaterPlanWeekAdapter;
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.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.Date;
import java.util.List;
import java.util.Locale;
public class WaterConfigFragment_copy extends BaseFragment<WaterConfigFragmentLayoutCopyBinding, WaterPlanPresenter>
implements WaterPlanContract.WaterPlanView {
//本地新增排程时的实体
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) {
// 设置菜单创建器。
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("1");
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);
initListener();
}
private void initListener() {
setClick(viewBinding.tvCommit);
setClick(viewBinding.imgAdd);
setClick(viewBinding.switchButton);
//头部 周一~周日
mWeekAdapter.setOnItemClickListener(new BaseQuickAdapter.OnItemClickListener() {
@Override
public void onItemClick(BaseQuickAdapter adapter, View view, int position) {
mWeekAdapter.setSelPos(position);
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;
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) {}
@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.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:
// 如果已经保存过mRemoteEntity 不为空),则走更新逻辑;否则走新增逻辑
if (mRemoteEntity != null) {
updateConfig();
} else {
validateAndSave();
}
break;
}
}
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();
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};
//时间选择器
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))
.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 (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());
}
@Override
public void onNetChange(int netModel) {
}
@Override
public void showError(String message) {
}
@Override
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,9 +1,13 @@
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;
@@ -33,6 +37,7 @@ public class WaterPlanFragment extends BaseFragment<WaterPlanFragmentBinding, Wa
private List<WaterPlanWeekEntity> mPlanList = new ArrayList<>();
private WaterPlanListAdapter mAdapter;
private int mCurrentPage = 1;
private String mSearchOption = "";
@Override
public void initData(Bundle state) {
@@ -47,6 +52,7 @@ 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,mPlanList);
viewBinding.rvPlans.setAdapter(mAdapter);
@@ -63,13 +69,36 @@ public class WaterPlanFragment extends BaseFragment<WaterPlanFragmentBinding, Wa
viewBinding.refresh.setRefreshHeader(header);
viewBinding.refresh.setRefreshFooter(new ClassicsFooter(mContext));
viewBinding.refresh.setOnRefreshListener(layout -> {
mSearchOption = "";
mCurrentPage = 1;
viewBinding.refresh.setNoMoreData(false);
mPresenter.getWaterPlanList(mCurrentPage);
mPresenter.getWaterPlanList(mCurrentPage,mSearchOption);
viewBinding.etInputPlanName.setText("");
});
viewBinding.refresh.setOnLoadMoreListener(layout -> {
mCurrentPage++;
mPresenter.getWaterPlanList(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;
});
}
@@ -77,12 +106,13 @@ public class WaterPlanFragment extends BaseFragment<WaterPlanFragmentBinding, Wa
protected void onResumeInitData() {
super.onResumeInitData();
showLoadingDialog();
mPresenter.getWaterPlanList(mCurrentPage);
mPresenter.getWaterPlanList(mCurrentPage,mSearchOption);
}
private void initListener() {
setClick(viewBinding.tvAdd);
setClick(viewBinding.includedNoresult.btnRefresh);
setClick(viewBinding.includedNoresult.tvAddPlan);
}
private void setClick(View view) {
@@ -92,12 +122,13 @@ 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);
mPresenter.getWaterPlanList(mCurrentPage,mSearchOption);
break;
}
}
@@ -121,7 +152,7 @@ public class WaterPlanFragment extends BaseFragment<WaterPlanFragmentBinding, Wa
if (mAdapter.getItemCount() >= total || pageList.size() == 0) {
// 使用 post 延迟调用,避免内部状态冲突导致的循环调用
viewBinding.refresh.postDelayed(() -> viewBinding.refresh.setNoMoreData(true), 300);
viewBinding.relNoMore.setVisibility(View.VISIBLE); // 自定义底部提示"暂无更多数据"
viewBinding.relNoMore.setVisibility(VISIBLE); // 自定义底部提示"暂无更多数据"
} else {
viewBinding.refresh.setNoMoreData(false);
viewBinding.relNoMore.setVisibility(View.GONE);
@@ -129,11 +160,11 @@ public class WaterPlanFragment extends BaseFragment<WaterPlanFragmentBinding, Wa
// 5. 控制空布局和内容显示
if (mAdapter.getItemCount() != 0) {
viewBinding.refresh.setVisibility(View.VISIBLE);
viewBinding.refresh.setVisibility(VISIBLE);
viewBinding.relNoresult.setVisibility(View.GONE);
} else {
viewBinding.refresh.setVisibility(View.GONE);
viewBinding.relNoresult.setVisibility(View.VISIBLE);
viewBinding.relNoresult.setVisibility(VISIBLE);
}
}

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;
@@ -24,8 +25,19 @@ public class WaterPlanListAdapter extends BaseQuickAdapter<WaterPlanWeekEntity,
@Override
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

@@ -26,6 +26,7 @@ public class WaterPlanWeekEntity implements Serializable {
private String userId;
private String name;
private List<WaterDeviceEntity> deviceIds;
private List<WaterDeviceEntity> deviceNos;
private String status = "1";
private List<DetailsBean> details;

View File

@@ -24,10 +24,11 @@ public class WaterPlanPresenter extends BasePresenter<WaterPlanContract.WaterPla
/**
* 获取排程信息
*/
public void getWaterPlanList(int mCurrentPage) {
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
@@ -195,19 +196,19 @@ public class WaterPlanPresenter extends BasePresenter<WaterPlanContract.WaterPla
/**
* 排程绑定设备
* @param entity
* @param deviceIds
* @param deviceNo
*/
public void planBindWithDevices(WaterPlanWeekEntity entity, String deviceIds) {
public void planBindWithDevices(WaterPlanWeekEntity entity, String deviceNo) {
try {
JSONObject json = new JSONObject();
json.put("scheduleId", entity.getId());
// 将逗号分隔的字符串转换为 JSONArray (数字类型)
JSONArray deviceIdArray = new JSONArray();
String[] idArray = deviceIds.split(",");
String[] idArray = deviceNo.split(",");
for (String id : idArray) {
deviceIdArray.put(id);
}
json.put("deviceIds", deviceIdArray);
json.put("deviceNos", deviceIdArray);
impl.planBindDevice(json, new WaterPlanContract.CallBack<BaseBean>() {
@Override
public void success(BaseBean bean, int total) {
@@ -288,7 +289,7 @@ public class WaterPlanPresenter extends BasePresenter<WaterPlanContract.WaterPla
public void planUnbindDevice(String planID, String deviceID,int position) {
Map<String,String> map = new HashMap<>();
map.put("scheduleId",planID);
map.put("deviceId",deviceID);
map.put("deviceNo",deviceID);
impl.planUnbindDevice(map, new WaterPlanContract.CallBack<BaseBean>() {
@Override
public void success(BaseBean bean, int total) {

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()));
}
}

View File

@@ -1,76 +0,0 @@
package com.ckkj.water.plate.adapter;
import android.content.Context;
import androidx.annotation.Nullable;
import androidx.core.content.ContextCompat;
import com.chad.library.adapter.base.BaseQuickAdapter;
import com.chad.library.adapter.base.BaseViewHolder;
import com.ckkj.water.R;
import com.ckkj.water.plate.entity.BaziResultBean;
import com.ckkj.water.utils.helper.ShiShenCalculator;
import java.util.List;
/**
* @author fengxiaoyang
* @date 2025/8/5
* @description TODO: 描述该类的作用
*/
public class DayunAdapter extends BaseQuickAdapter<BaziResultBean.DetailInfoDTO.DayunInfoDTO, BaseViewHolder> {
private Context mContext;
private int mSelPos = -1;
public DayunAdapter(Context context,int layoutResId, @Nullable List<BaziResultBean.DetailInfoDTO.DayunInfoDTO> data,
BaziResultBean.DetailInfoDTO.SizhuInfoDTO sizhuInfoDTO) {
super(layoutResId, data);
this.mContext = context;
}
public int getmSelPos() {
return mSelPos;
}
@Override
protected void convert(BaseViewHolder holder, BaziResultBean.DetailInfoDTO.DayunInfoDTO item) {
holder.setText(R.id.tv_year,item.getDayunStartYear() + "");
if(holder.getLayoutPosition() != 0){
holder.setText(R.id.tv_age,item.getDayunStartAge() + "");
holder.setText(R.id.tv_gan_value,ShiShenCalculator.getAbbreviation(item.getDayunShishen()));
holder.setText(R.id.tv_zhi_value,ShiShenCalculator.getAbbreviation(item.getDayunYearDzGod().get(0)));
holder.setGone(R.id.tv_gan_value,true);
holder.setGone(R.id.tv_zhi_value,true);
holder.setGone(R.id.tv_zhi_key,true);
holder.setText(R.id.tv_gan_key,item.getDayunYearTg());
holder.setText(R.id.tv_zhi_key,item.getDayunYearDz());
}else{
int dyStart = item.getDayunStartYear();
int dyEnd = item.getDayunEndYear();
if(dyStart > dyEnd){
holder.setText(R.id.tv_age,"0岁");
}else if(dyStart == dyEnd){
holder.setText(R.id.tv_age,"1岁");
}else{
holder.setText(R.id.tv_age,item.getDayunStartAge() + "-" + item.getDayunEndAge() + "");
}
holder.setGone(R.id.tv_gan_value,false);
holder.setGone(R.id.tv_zhi_value,false);
holder.setText(R.id.tv_gan_key,item.getDayunTongxian());
holder.setGone(R.id.tv_zhi_key,false);
holder.setGone(R.id.tv_zhi_value,false);
}
if(holder.getLayoutPosition() == mSelPos){
holder.setBackgroundColor(R.id.ll_item, ContextCompat.getColor(mContext,R.color.divider));
}else{
holder.setBackgroundColor(R.id.ll_item, ContextCompat.getColor(mContext,R.color.white));
}
}
public void setSelPostion(int pos){
this.mSelPos = pos;
notifyDataSetChanged();
}
}

View File

@@ -1,167 +0,0 @@
package com.ckkj.water.plate.adapter;
import android.content.Context;
import android.graphics.Color;
import android.text.TextUtils;
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.plate.entity.BaziResultBean;
import com.ckkj.water.utils.helper.FiveElementsHelper;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* @author fengxiaoyang
* @date 2025/8/6
* @description 大运、流年、流月柱状图适配器
*/
public class DayunColumnAdapter extends BaseQuickAdapter<BaziResultBean.DetailInfoDTO.DayunInfoDTO, BaseViewHolder> {
private Context mContext;
private int mDayunTypeCode = 100;
private CangGanAdapter mCangganAdapter;
private ShenshaAdapter mShenshaAdapter;
private int mSelectXiaoyunPos = -1;
public DayunColumnAdapter(Context context, int layoutResId,
@Nullable List<BaziResultBean.DetailInfoDTO.DayunInfoDTO> data,
int typeCode) {
super(layoutResId, data);
this.mContext = context;
this.mDayunTypeCode = typeCode;
}
@Override
protected void convert(BaseViewHolder holder, BaziResultBean.DetailInfoDTO.DayunInfoDTO item) {
RecyclerView rvDatas = holder.getView(R.id.rv_canggan);
RecyclerView rvShenShaData = holder.getView(R.id.rv_shensha_data);
holder.setGone(R.id.viewline,true);
switch (mDayunTypeCode) {
case 100: // 大运
// 第一个itembornBean童限 的特殊处理
holder.setText(R.id.tv_shishen, item.isTongXian() ?
item.getXiaoyunInfo().get(0).getXiaoyunShishen() : item.getDayunShishen());
holder.setText(R.id.tv_tg, item.isTongXian() ?
item.getXiaoyunInfo().get(0).getXiaoyunYearTg() : item.getDayunYearTg());
holder.setText(R.id.tv_dz, item.isTongXian() ?
item.getXiaoyunInfo().get(0).getXiaoyunYearDz() : item.getDayunYearDz());
holder.setTextColor(R.id.tv_tg, Color.parseColor(FiveElementsHelper.getElementInfo
(item.isTongXian() ?
item.getXiaoyunInfo().get(0).getXiaoyunYearTg() : item.getDayunYearTg()).get("color")));
holder.setTextColor(R.id.tv_dz, Color.parseColor(FiveElementsHelper.getElementInfo
(item.isTongXian() ?
item.getXiaoyunInfo().get(0).getXiaoyunYearTg() : item.getDayunYearTg()).get("color")));
holder.setText(R.id.tv_xingyun, item.isTongXian() ?
item.getXiaoyunInfo().get(0).getXiaoyunDzStarCs() : item.getDayunDzStarCs());
holder.setText(R.id.tv_zizuo, item.isTongXian() ?
item.getXiaoyunInfo().get(0).getXiaoyunDzSelfCs() : item.getDayunDzSelfCs());
holder.setText(R.id.tv_kongwang, item.isTongXian() ?
item.getXiaoyunInfo().get(0).getXiaoyunKongwang() : item.getDayunKongwang());
holder.setText(R.id.tv_nayin, item.isTongXian() ?
item.getXiaoyunInfo().get(0).getXiaoyunNayin() : item.getDayunNayin());
// bornBean可能没有藏干和神煞数据需要特殊处理
if (mCangganAdapter == null) {
mCangganAdapter = new CangGanAdapter(mContext,
R.layout.paipan_canggan_item,
item.isTongXian() ? item.getXiaoyunInfo().get(0).getXiaoyunYearCg() : item.getDayunYearCg(),
item.isTongXian() ? item.getXiaoyunInfo().get(0).getXiaoyunDzGod() : item.getDayunYearDzGod());
rvDatas.setAdapter(mCangganAdapter);
} else {
mCangganAdapter.setNewData(item.isTongXian() ?
item.getXiaoyunInfo().get(0).getXiaoyunYearCg() : item.getDayunYearCg());
mCangganAdapter.setmDzGodList(item.isTongXian() ?
item.getXiaoyunInfo().get(0).getXiaoyunDzGod() : item.getDayunYearDzGod());
}
List<String> shenshaList = new ArrayList<>();
if (item.isTongXian()) {
String shensha = item.getXiaoyunInfo().get(0).getXiaoyunShensha();
if (!TextUtils.isEmpty(shensha)) {
shenshaList = Arrays.asList(shensha.split(" "));
}
} else {
String shensha = item.getDayunShensha();
if (!TextUtils.isEmpty(shensha)) {
shenshaList = Arrays.asList(shensha.split(" "));
}
}
if (mShenshaAdapter == null) {
mShenshaAdapter = new ShenshaAdapter(mContext, R.layout.paipan_shensha_item, shenshaList);
rvShenShaData.setAdapter(mShenshaAdapter);
} else {
mShenshaAdapter.setNewData(shenshaList);
}
break;
case 200: // 流年
BaziResultBean.DetailInfoDTO.DayunInfoDTO.XiaoyunInfoDTO xiaoyunEntity = item.getXiaoyunInfo().get(mSelectXiaoyunPos);
// 第一个itembornBean的特殊处理
holder.setText(R.id.tv_shishen, xiaoyunEntity.getXiaoyunShishen());
holder.setText(R.id.tv_tg, xiaoyunEntity.getXiaoyunYearTg());
holder.setText(R.id.tv_dz, xiaoyunEntity.getXiaoyunYearDz());
holder.setTextColor(R.id.tv_tg, Color.parseColor(FiveElementsHelper.getElementInfo(xiaoyunEntity.getXiaoyunYearTg()).get("color")));
holder.setTextColor(R.id.tv_dz, Color.parseColor(FiveElementsHelper.getElementInfo(xiaoyunEntity.getXiaoyunYearDz()).get("color")));
holder.setText(R.id.tv_xingyun, xiaoyunEntity.getXiaoyunDzStarCs());
holder.setText(R.id.tv_zizuo, xiaoyunEntity.getXiaoyunDzSelfCs());
holder.setText(R.id.tv_kongwang, xiaoyunEntity.getXiaoyunKongwang());
holder.setText(R.id.tv_nayin, xiaoyunEntity.getXiaoyunNayin());
// bornBean的流年数据可能为空需要特殊处理
if (mCangganAdapter == null) {
mCangganAdapter = new CangGanAdapter(mContext, R.layout.paipan_canggan_item,
xiaoyunEntity.getXiaoyunYearCg(), xiaoyunEntity.getXiaoyunDzGod());
rvDatas.setAdapter(mCangganAdapter);
}else{
mCangganAdapter.setNewData(xiaoyunEntity.getXiaoyunYearCg());
mCangganAdapter.setmDzGodList(xiaoyunEntity.getXiaoyunDzGod());
}
if (mShenshaAdapter == null) {
String shensha = xiaoyunEntity.getXiaoyunShensha();
mShenshaAdapter = new ShenshaAdapter(mContext, R.layout.paipan_shensha_item, Arrays.asList(shensha.split(" ")));
rvShenShaData.setAdapter(mShenshaAdapter);
}else{
String shensha = xiaoyunEntity.getXiaoyunShensha();
mShenshaAdapter.setNewData(Arrays.asList(shensha.split(" ")));
}
break;
case 300: // 流月
// 第一个itembornBean的特殊处理
holder.setText(R.id.tv_shishen, "小运");
holder.setText(R.id.tv_tg, item.getDayunYearTg());
holder.setText(R.id.tv_dz, item.getDayunYearDz());
holder.setTextColor(R.id.tv_tg, Color.parseColor(FiveElementsHelper.getElementInfo(item.getDayunYearTg()).get("color")));
holder.setTextColor(R.id.tv_dz, Color.parseColor(FiveElementsHelper.getElementInfo(item.getDayunYearDz()).get("color")));
holder.setText(R.id.tv_xingyun, "");
holder.setText(R.id.tv_zizuo, "");
holder.setText(R.id.tv_kongwang, "");
holder.setText(R.id.tv_nayin, "");
// bornBean的流月数据可能为空需要特殊处理
if (mCangganAdapter == null) {
mCangganAdapter = new CangGanAdapter(mContext, R.layout.paipan_canggan_item,
Arrays.asList(), Arrays.asList());
rvDatas.setAdapter(mCangganAdapter);
}
if (mShenshaAdapter == null) {
mShenshaAdapter = new ShenshaAdapter(mContext, R.layout.paipan_shensha_item, Arrays.asList());
rvShenShaData.setAdapter(mShenshaAdapter);
}
break;
}
}
public void setColumnCode(int code,int xiaoyunPos) {
mDayunTypeCode = code;
mSelectXiaoyunPos = xiaoyunPos;
notifyDataSetChanged();
}
}

View File

@@ -1,77 +0,0 @@
package com.ckkj.water.plate.adapter;
import android.content.Context;
import android.graphics.Color;
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.plate.entity.BaziResultBean;
import com.ckkj.water.utils.helper.FiveElementsHelper;
import java.util.Arrays;
import java.util.List;
/**
* @author fengxiaoyang
* @date 2025/8/7
* @description TODO: 描述该类的作用
*/
public class LiuNianColumnAdapter extends BaseQuickAdapter
<BaziResultBean.DetailInfoDTO.DayunInfoDTO.LiunianInfoDTO, BaseViewHolder> {
private CangGanAdapter mCangganAdapter;
private ShenshaAdapter mShenshaAdapter;
private Context mContext;
private List<BaziResultBean.DetailInfoDTO.DayunInfoDTO.XiaoyunInfoDTO> xiaoyunInfo;
public LiuNianColumnAdapter(Context context, int layoutResId,
@Nullable List<BaziResultBean.DetailInfoDTO.DayunInfoDTO.LiunianInfoDTO> data,
List<BaziResultBean.DetailInfoDTO.DayunInfoDTO.XiaoyunInfoDTO> xiaoyunInfo) {
super(layoutResId, data);
this.mContext = context;
this.xiaoyunInfo = xiaoyunInfo;
}
@Override
protected void convert(BaseViewHolder holder, BaziResultBean.DetailInfoDTO.DayunInfoDTO.LiunianInfoDTO item) {
RecyclerView rvDatas = holder.getView(R.id.rv_canggan);
RecyclerView rvShenShaData = holder.getView(R.id.rv_shensha_data);
// 第一个itembornBean的特殊处理
holder.setText(R.id.tv_shishen, item.getLiunianShishen());
holder.setText(R.id.tv_tg, item.getLiunianYearTg());
holder.setText(R.id.tv_dz, item.getLiunianYearDz());
holder.setTextColor(R.id.tv_tg, Color.parseColor(FiveElementsHelper.getElementInfo(item.getLiunianYearTg()).get("color")));
holder.setTextColor(R.id.tv_dz, Color.parseColor(FiveElementsHelper.getElementInfo(item.getLiunianYearDz()).get("color")));
holder.setText(R.id.tv_xingyun, item.getLiunianDzStarCs());
holder.setText(R.id.tv_zizuo, item.getLiunianDzSelfCs());
holder.setText(R.id.tv_kongwang, item.getLiunianKongwang());
holder.setText(R.id.tv_nayin, item.getLiunianNayin());
// bornBean的流年数据可能为空需要特殊处理
if (mCangganAdapter == null) {
mCangganAdapter = new CangGanAdapter(mContext, R.layout.paipan_canggan_item,
item.getLiunianYearCg(), item.getLiunianDzGod());
rvDatas.setAdapter(mCangganAdapter);
}else{
mCangganAdapter.setNewData(item.getLiunianYearCg());
mCangganAdapter.setmDzGodList(item.getLiunianDzGod());
}
if (mShenshaAdapter == null) {
mShenshaAdapter = new ShenshaAdapter(mContext, R.layout.paipan_shensha_item, Arrays.asList(item.getLiunianShensha().split(" ")));
rvShenShaData.setAdapter(mShenshaAdapter);
}else{
String shensha = item.getLiunianShensha();
mShenshaAdapter.setNewData(Arrays.asList(shensha.split(" ")));
}
}
public void setXiaoyunDatas(List<BaziResultBean.DetailInfoDTO.DayunInfoDTO.XiaoyunInfoDTO> xiaoyunInfoDTOList) {
this.xiaoyunInfo = xiaoyunInfoDTOList;
}
}

View File

@@ -1,75 +0,0 @@
package com.ckkj.water.plate.adapter;
import android.content.Context;
import android.graphics.Color;
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.plate.entity.BaziResultBean;
import com.ckkj.water.utils.helper.FiveElementsHelper;
import java.util.Arrays;
import java.util.List;
/**
* @author fengxiaoyang
* @date 2025/8/7
* @description TODO: 描述该类的作用
*/
public class LiuYueColumnAdapter extends BaseQuickAdapter
<BaziResultBean.DetailInfoDTO.DayunInfoDTO.LiunianInfoDTO.LiuyueInfoDTO, BaseViewHolder> {
private CangGanAdapter mCangganAdapter;
private ShenshaAdapter mShenshaAdapter;
private Context mContext;
private List<BaziResultBean.DetailInfoDTO.DayunInfoDTO.XiaoyunInfoDTO> xiaoyunInfo;
public LiuYueColumnAdapter(Context context, int layoutResId,
@Nullable List<BaziResultBean.DetailInfoDTO.DayunInfoDTO.LiunianInfoDTO.LiuyueInfoDTO> data) {
super(layoutResId, data);
this.mContext = context;
}
@Override
protected void convert(BaseViewHolder holder, BaziResultBean.DetailInfoDTO.DayunInfoDTO.LiunianInfoDTO.LiuyueInfoDTO item) {
RecyclerView rvDatas = holder.getView(R.id.rv_canggan);
RecyclerView rvShenShaData = holder.getView(R.id.rv_shensha_data);
// 第一个itembornBean的特殊处理
holder.setText(R.id.tv_shishen, item.getLiuyueShishen());
holder.setText(R.id.tv_tg, item.getLiuyueMonthTg());
holder.setText(R.id.tv_dz, item.getLiuyueMonthDz());
holder.setTextColor(R.id.tv_tg, Color.parseColor(FiveElementsHelper.getElementInfo(item.getLiuyueMonthTg()).get("color")));
holder.setTextColor(R.id.tv_dz, Color.parseColor(FiveElementsHelper.getElementInfo(item.getLiuyueMonthDz()).get("color")));
holder.setText(R.id.tv_xingyun, item.getLiuyueDzStarCs());
holder.setText(R.id.tv_zizuo, item.getLiuyueDzSelfCs());
holder.setText(R.id.tv_kongwang, item.getLiuyueKongwang());
holder.setText(R.id.tv_nayin, item.getLiuyueNayin());
// bornBean的流年数据可能为空需要特殊处理
if (mCangganAdapter == null) {
mCangganAdapter = new CangGanAdapter(mContext, R.layout.paipan_canggan_item,
item.getLiuyueMonthCg(), item.getLiuyueMonthDzGod());
rvDatas.setAdapter(mCangganAdapter);
}else{
mCangganAdapter.setNewData(item.getLiuyueMonthCg());
mCangganAdapter.setmDzGodList(item.getLiuyueMonthDzGod());
}
if (mShenshaAdapter == null) {
mShenshaAdapter = new ShenshaAdapter(mContext, R.layout.paipan_shensha_item, Arrays.asList(item.getLiuyueShensha().split(" ")));
rvShenShaData.setAdapter(mShenshaAdapter);
}else{
String shensha = item.getLiuyueShensha();
mShenshaAdapter.setNewData(Arrays.asList(shensha.split(" ")));
}
}
// public void setXiaoyunDatas(List<BaziResultBean.DetailInfoDTO.DayunInfoDTO.XiaoyunInfoDTO> xiaoyunInfoDTOList) {
// this.xiaoyunInfo = xiaoyunInfoDTOList;
// }
}

View File

@@ -1,63 +0,0 @@
package com.ckkj.water.plate.adapter;
import android.content.Context;
import androidx.annotation.Nullable;
import androidx.core.content.ContextCompat;
import com.chad.library.adapter.base.BaseQuickAdapter;
import com.chad.library.adapter.base.BaseViewHolder;
import com.ckkj.water.R;
import com.ckkj.water.plate.entity.BaziResultBean;
import com.ckkj.water.utils.helper.ShiShenCalculator;
import java.util.ArrayList;
import java.util.List;
/**
* @author fengxiaoyang
* @date 2025/8/6
* @description TODO: 描述该类的作用
*/
public class LiunianAdapter extends BaseQuickAdapter<BaziResultBean.DetailInfoDTO.DayunInfoDTO.LiunianInfoDTO, BaseViewHolder> {
private Context mContext;
private int mSelPos = -1;
private List<BaziResultBean.DetailInfoDTO.DayunInfoDTO.XiaoyunInfoDTO> xiaoyunList =
new ArrayList<>();
public LiunianAdapter(Context context, int layoutResId,
@Nullable List<BaziResultBean.DetailInfoDTO.DayunInfoDTO.LiunianInfoDTO> data,
List<BaziResultBean.DetailInfoDTO.DayunInfoDTO.XiaoyunInfoDTO> xiaoyunInfo) {
super(layoutResId, data);
this.mContext = context;
this.xiaoyunList = xiaoyunInfo;
}
@Override
protected void convert(BaseViewHolder holder, BaziResultBean.DetailInfoDTO.DayunInfoDTO.LiunianInfoDTO item) {
holder.setText(R.id.tv_year,item.getLiunianYear() + "");
holder.setGone(R.id.tv_age,false);
holder.setText(R.id.tv_gan_value, ShiShenCalculator.getAbbreviation(item.getLiunianTgGod()));
holder.setText(R.id.tv_zhi_value,ShiShenCalculator.getAbbreviation(item.getLiunianDzGod().get(0)));
holder.setText(R.id.tv_gan_key,item.getLiunianYearTg());
holder.setText(R.id.tv_zhi_key,item.getLiunianYearDz());
holder.setGone(R.id.tv_xiaoyun,true);
holder.setText(R.id.tv_xiaoyun,xiaoyunList.get(holder.getLayoutPosition()).getXiaoyunGanzhi());
if(holder.getLayoutPosition() == mSelPos){
holder.setBackgroundColor(R.id.ll_item, ContextCompat.getColor(mContext,R.color.divider));
}else{
holder.setBackgroundColor(R.id.ll_item, ContextCompat.getColor(mContext,R.color.white));
}
}
public void setSelPostion(int pos){
this.mSelPos = pos;
notifyDataSetChanged();
}
public int getmSelPos() {
return mSelPos;
}
}

View File

@@ -1,64 +0,0 @@
package com.ckkj.water.plate.adapter;
import android.content.Context;
import androidx.annotation.Nullable;
import androidx.core.content.ContextCompat;
import com.chad.library.adapter.base.BaseQuickAdapter;
import com.chad.library.adapter.base.BaseViewHolder;
import com.ckkj.water.R;
import com.ckkj.water.plate.entity.BaziResultBean;
import com.ckkj.water.utils.helper.ShiShenCalculator;
import com.ckkj.water.utils.time.ZYTimeUtils;
import java.util.ArrayList;
import java.util.List;
/**
* @author fengxiaoyang
* @date 2025/8/6
* @description TODO: 描述该类的作用
*/
public class LiuyueAdapter extends BaseQuickAdapter<BaziResultBean.DetailInfoDTO.DayunInfoDTO.
LiunianInfoDTO.LiuyueInfoDTO, BaseViewHolder> {
private Context mContext;
private int mSelPos = -1;
private List<BaziResultBean.DetailInfoDTO.DayunInfoDTO.LiunianInfoDTO.LiunianJieqiDTO> jieqiList =
new ArrayList<>();
public LiuyueAdapter(Context context,int layoutResId, @Nullable List<BaziResultBean.DetailInfoDTO.DayunInfoDTO.LiunianInfoDTO.LiuyueInfoDTO> data,
List<BaziResultBean.DetailInfoDTO.DayunInfoDTO.LiunianInfoDTO.LiunianJieqiDTO> jieqiList) {
super(layoutResId, data);
this.mContext = context;
this.jieqiList = jieqiList;
}
@Override
protected void convert(BaseViewHolder holder, BaziResultBean.DetailInfoDTO.DayunInfoDTO.LiunianInfoDTO.LiuyueInfoDTO item) {
holder.setText(R.id.tv_year,jieqiList.get(holder.getLayoutPosition()).getJieqiName());
holder.setGone(R.id.tv_age,true);
//节气日期转换
String jieqiDate = ZYTimeUtils.formatToMonthDay(jieqiList.get(holder.getLayoutPosition()).getJieqiSolarYmdhms());
holder.setText(R.id.tv_age, jieqiDate);
holder.setText(R.id.tv_gan_value, ShiShenCalculator.getAbbreviation(item.getLiuyueMonthTgGod()));
holder.setText(R.id.tv_zhi_value,ShiShenCalculator.getAbbreviation(item.getLiuyueMonthDzGod().get(0)));
holder.setText(R.id.tv_gan_key,item.getLiuyueMonthTg());
holder.setText(R.id.tv_zhi_key,item.getLiuyueMonthDz());
holder.setGone(R.id.tv_xiaoyun,false);
if(holder.getLayoutPosition() == mSelPos){
holder.setBackgroundColor(R.id.ll_item, ContextCompat.getColor(mContext,R.color.divider));
}else{
holder.setBackgroundColor(R.id.ll_item, ContextCompat.getColor(mContext,R.color.white));
}
}
public void setSelPostion(int pos){
this.mSelPos = pos;
notifyDataSetChanged();
}
public int getmSelPos() {
return mSelPos;
}
}

View File

@@ -1,60 +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.plate.entity.PaipanHistoryEntity;
import com.ckkj.water.utils.click.ClickUtil;
import com.ckkj.water.utils.helper.FiveElementsHelper;
import java.util.List;
/**
* @author fengxiaoyang
* @date 2025/8/9
* @description TODO: 描述该类的作用
*/
public class PaipanHistoryAdapter extends BaseQuickAdapter<PaipanHistoryEntity.RecordsDTO, BaseViewHolder> {
private Context mContext;
public PaipanHistoryAdapter(Context context,int layoutResId, @Nullable List<PaipanHistoryEntity.RecordsDTO> data) {
super(layoutResId, data);
this.mContext = context;
}
@Override
protected void convert(BaseViewHolder holder, PaipanHistoryEntity.RecordsDTO item) {
String []nianArr = item.getNianZhu().split(",");
String []yueArr = item.getYueZhu().split(",");
String []riArr = item.getRiZhu().split(",");
String []shiArr = item.getShiZhu().split(",");
holder.setText(R.id.tv_nian_tg,nianArr[0]);
holder.setText(R.id.tv_nian_dz,nianArr[1]);
holder.setText(R.id.tv_yue_tg,yueArr[0]);
holder.setText(R.id.tv_yue_dz,yueArr[1]);
holder.setText(R.id.tv_ri_tg,riArr[0]);
holder.setText(R.id.tv_ri_dz,riArr[1]);
holder.setText(R.id.tv_shi_tg,shiArr[0]);
holder.setText(R.id.tv_shi_dz,shiArr[1]);
holder.setTextColor(R.id.tv_nian_tg, Color.parseColor(FiveElementsHelper.getElementInfo(nianArr[0]).get("color")));
holder.setTextColor(R.id.tv_nian_dz, Color.parseColor(FiveElementsHelper.getElementInfo(nianArr[1]).get("color")));
holder.setTextColor(R.id.tv_yue_tg, Color.parseColor(FiveElementsHelper.getElementInfo(yueArr[0]).get("color")));
holder.setTextColor(R.id.tv_yue_dz, Color.parseColor(FiveElementsHelper.getElementInfo(yueArr[1]).get("color")));
holder.setTextColor(R.id.tv_ri_tg, Color.parseColor(FiveElementsHelper.getElementInfo(riArr[0]).get("color")));
holder.setTextColor(R.id.tv_ri_dz, Color.parseColor(FiveElementsHelper.getElementInfo(riArr[1]).get("color")));
holder.setTextColor(R.id.tv_shi_tg, Color.parseColor(FiveElementsHelper.getElementInfo(shiArr[0]).get("color")));
holder.setTextColor(R.id.tv_shi_dz, Color.parseColor(FiveElementsHelper.getElementInfo(shiArr[1]).get("color")));
holder.setText(R.id.tv_user_name,item.getName());
holder.setText(R.id.tv_user_sex,Integer.parseInt(item.getGender()) == 0 ? "":"");
holder.setText(R.id.tv_user_birthtime,Integer.parseInt(item.getBirthType()) == 1 ?
"公历:" + item.getYangLiBirthTime():
"农历:" + item.getYinLiBirthTime());
ClickUtil.addClickPart(holder.getView(R.id.img_delete),80);
holder.addOnClickListener(R.id.img_delete);
}
}

View File

@@ -1,30 +0,0 @@
package com.ckkj.water.plate.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 java.util.List;
/**
* @author fengxiaoyang
* @date 2025/8/6
* @description TODO: 描述该类的作用
*/
public class ShenshaAdapter extends BaseQuickAdapter<String, BaseViewHolder> {
private Context mContext;
public ShenshaAdapter(Context context,int layoutResId, @Nullable List<String> data) {
super(layoutResId, data);
this.mContext = context;
}
@Override
protected void convert(BaseViewHolder helper, String item) {
helper.setText(R.id.tv_shensha_value,item);
}
}

View File

@@ -1,128 +0,0 @@
package com.ckkj.water.plate.adapter;
import android.content.Context;
import android.graphics.Color;
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.plate.entity.BaziResultBean;
import com.ckkj.water.utils.helper.FiveElementsHelper;
import java.util.Arrays;
import java.util.List;
/**
* @author fengxiaoyang
* @date 2025/8/6
* @description TODO: 描述该类的作用
*/
public class SizhuAdapter extends BaseQuickAdapter<BaziResultBean.DetailInfoDTO.SizhuInfoDTO, BaseViewHolder> {
private Context mContext;
private int mSizhuTypeCode = 100;
private CangGanAdapter mCangganAdapter;
private ShenshaAdapter mShenshaAdapter;
public SizhuAdapter(Context context,int layoutResId,
@Nullable List<BaziResultBean.DetailInfoDTO.SizhuInfoDTO> data,
int typeCode) {
super(layoutResId, data);
this.mContext = context;
this.mSizhuTypeCode = typeCode;
}
@Override
protected void convert(BaseViewHolder holder, BaziResultBean.DetailInfoDTO.SizhuInfoDTO item) {
RecyclerView rvDatas = holder.getView(R.id.rv_canggan);
RecyclerView rvShenShaData = holder.getView(R.id.rv_shensha_data);
switch (mSizhuTypeCode){
case 100: // 年柱
holder.setText(R.id.tv_shishen,item.getYear().getTgGod());
holder.setText(R.id.tv_tg,item.getYear().getTg());
holder.setText(R.id.tv_dz,item.getYear().getDz());
holder.setTextColor(R.id.tv_tg, Color.parseColor(FiveElementsHelper.getElementInfo(item.getYear().getTg()).get("color")));
holder.setTextColor(R.id.tv_dz, Color.parseColor(FiveElementsHelper.getElementInfo(item.getYear().getDz()).get("color")));
holder.setText(R.id.tv_xingyun,item.getYear().getDzStarCs());
holder.setText(R.id.tv_zizuo,item.getYear().getDzSelfCs());
holder.setText(R.id.tv_kongwang,item.getYear().getKw());
holder.setText(R.id.tv_nayin,item.getYear().getNy());
if(mCangganAdapter == null){
mCangganAdapter = new CangGanAdapter(mContext,R.layout.paipan_canggan_item,
item.getYear().getCg(), item.getYear().getDzGod());
rvDatas.setAdapter(mCangganAdapter);
}
if(mShenshaAdapter == null){
List<String> shenshaList = Arrays.asList(item.getYear().getShensha().split(" "));
mShenshaAdapter = new ShenshaAdapter(mContext,R.layout.paipan_shensha_item,shenshaList);
rvShenShaData.setAdapter(mShenshaAdapter);
}
break;
case 200: // 月柱
holder.setText(R.id.tv_shishen,item.getMonth().getTgGod());
holder.setText(R.id.tv_tg,item.getMonth().getTg());
holder.setText(R.id.tv_dz,item.getMonth().getDz());
holder.setTextColor(R.id.tv_tg, Color.parseColor(FiveElementsHelper.getElementInfo(item.getMonth().getTg()).get("color")));
holder.setTextColor(R.id.tv_dz, Color.parseColor(FiveElementsHelper.getElementInfo(item.getMonth().getDz()).get("color")));
holder.setText(R.id.tv_xingyun,item.getMonth().getDzStarCs());
holder.setText(R.id.tv_zizuo,item.getMonth().getDzSelfCs());
holder.setText(R.id.tv_kongwang,item.getMonth().getKw());
holder.setText(R.id.tv_nayin,item.getMonth().getNy());
if(mCangganAdapter == null){
mCangganAdapter = new CangGanAdapter(mContext,R.layout.paipan_canggan_item,
item.getMonth().getCg(), item.getMonth().getDzGod());
rvDatas.setAdapter(mCangganAdapter);
}
if(mShenshaAdapter == null){
List<String> shenshaList = Arrays.asList(item.getMonth().getShensha().split(" "));
mShenshaAdapter = new ShenshaAdapter(mContext,R.layout.paipan_shensha_item,shenshaList);
rvShenShaData.setAdapter(mShenshaAdapter);
}
break;
case 300: // 日柱
holder.setText(R.id.tv_shishen,item.getDay().getTgGod());
holder.setText(R.id.tv_tg,item.getDay().getTg());
holder.setText(R.id.tv_dz,item.getDay().getDz());
holder.setTextColor(R.id.tv_tg, Color.parseColor(FiveElementsHelper.getElementInfo(item.getDay().getTg()).get("color")));
holder.setTextColor(R.id.tv_dz, Color.parseColor(FiveElementsHelper.getElementInfo(item.getDay().getDz()).get("color")));
holder.setText(R.id.tv_xingyun,item.getDay().getDzStarCs());
holder.setText(R.id.tv_zizuo,item.getDay().getDzSelfCs());
holder.setText(R.id.tv_kongwang,item.getDay().getKw());
holder.setText(R.id.tv_nayin,item.getDay().getNy());
if(mCangganAdapter == null){
mCangganAdapter = new CangGanAdapter(mContext,R.layout.paipan_canggan_item,
item.getDay().getCg(), item.getDay().getDzGod());
rvDatas.setAdapter(mCangganAdapter);
}
if(mShenshaAdapter == null){
List<String> shenshaList = Arrays.asList(item.getDay().getShensha().split(" "));
mShenshaAdapter = new ShenshaAdapter(mContext,R.layout.paipan_shensha_item,shenshaList);
rvShenShaData.setAdapter(mShenshaAdapter);
}
break;
case 400: // 时柱
holder.setText(R.id.tv_shishen,item.getHour().getTgGod());
holder.setText(R.id.tv_tg,item.getHour().getTg());
holder.setText(R.id.tv_dz,item.getHour().getDz());
holder.setTextColor(R.id.tv_tg, Color.parseColor(FiveElementsHelper.getElementInfo(item.getHour().getTg()).get("color")));
holder.setTextColor(R.id.tv_dz, Color.parseColor(FiveElementsHelper.getElementInfo(item.getHour().getDz()).get("color")));
holder.setText(R.id.tv_xingyun,item.getHour().getDzStarCs());
holder.setText(R.id.tv_zizuo,item.getHour().getDzSelfCs());
holder.setText(R.id.tv_kongwang,item.getHour().getKw());
holder.setText(R.id.tv_nayin,item.getHour().getNy());
if(mCangganAdapter == null){
mCangganAdapter = new CangGanAdapter(mContext,R.layout.paipan_canggan_item,
item.getHour().getCg(), item.getHour().getDzGod());
rvDatas.setAdapter(mCangganAdapter);
}
if(mShenshaAdapter == null){
List<String> shenshaList = Arrays.asList(item.getHour().getShensha().split(" "));
mShenshaAdapter = new ShenshaAdapter(mContext,R.layout.paipan_shensha_item,shenshaList);
rvShenShaData.setAdapter(mShenshaAdapter);
}
break;
}
}
}

View File

@@ -1,661 +0,0 @@
package com.ckkj.water.plate.entity;
import com.google.gson.annotations.SerializedName;
import java.io.Serializable;
import java.util.List;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @author fengxiaoyang
* @date 2025/8/5
* @description TODO: 描述该类的作用
*/
@NoArgsConstructor
@Data
public class BaziResultBean implements Serializable {
@SerializedName("base_info")
private BaseInfoDTO baseInfo;
@SerializedName("detail_info")
private DetailInfoDTO detailInfo;
@NoArgsConstructor
@Data
public static class BaseInfoDTO implements Serializable {
@SerializedName("sex")
private String sex;
@SerializedName("name")
private String name;
@SerializedName("gongli")
private String gongli;
@SerializedName("nongli")
private String nongli;
@SerializedName("qiyun")
private String qiyun;
@SerializedName("jiaoyun")
private String jiaoyun;
@SerializedName("taiyuan")
private String taiyuan;
@SerializedName("taiyuan_nayin")
private String taiyuanNayin;
@SerializedName("taixi")
private String taixi;
@SerializedName("taixi_nayin")
private String taixiNayin;
@SerializedName("minggong")
private String minggong;
@SerializedName("minggong_nayin")
private String minggongNayin;
@SerializedName("shengong")
private String shengong;
@SerializedName("shengong_nayin")
private String shengongNayin;
@SerializedName("shengxiao")
private String shengxiao;
@SerializedName("xingzuo")
private String xingzuo;
@SerializedName("siling")
private String siling;
@SerializedName("jiaoyun_mang")
private String jiaoyunMang;
@SerializedName("xingxiu")
private String xingxiu;
@SerializedName("minggua")
private MingguaDTO minggua;
@SerializedName("wuxing_wangdu")
private String wuxingWangdu;
@SerializedName("tiangan_liuyi")
private String tianganLiuyi;
@SerializedName("dizhi_liuyi")
private String dizhiLiuyi;
@SerializedName("zhengge")
private String zhengge;
@SerializedName("xiyongshen")
private XiyongshenDTO xiyongshen;
@SerializedName("wuxing_xiji")
private String wuxingXiji;
@NoArgsConstructor
@Data
public static class MingguaDTO implements Serializable {
@SerializedName("minggua_name")
private String mingguaName;
@SerializedName("minggua_fangwei")
private String mingguaFangwei;
}
@NoArgsConstructor
@Data
public static class XiyongshenDTO implements Serializable {
@SerializedName("qiangruo")
private String qiangruo;
@SerializedName("xiyongshen")
private String xiyongshen;
@SerializedName("jishen")
private String jishen;
@SerializedName("xiyongshen_desc")
private String xiyongshenDesc;
@SerializedName("jin_number")
private Integer jinNumber;
@SerializedName("mu_number")
private Integer muNumber;
@SerializedName("shui_number")
private Integer shuiNumber;
@SerializedName("huo_number")
private Integer huoNumber;
@SerializedName("tu_number")
private Integer tuNumber;
@SerializedName("zidang")
private Integer zidang;
@SerializedName("yidang")
private Integer yidang;
@SerializedName("zidang_percent")
private String zidangPercent;
@SerializedName("yidang_percent")
private String yidangPercent;
@SerializedName("tonglei")
private String tonglei;
@SerializedName("yilei")
private String yilei;
@SerializedName("rizhu_tiangan")
private String rizhuTiangan;
@SerializedName("jin_score")
private Integer jinScore;
@SerializedName("mu_score")
private Integer muScore;
@SerializedName("shui_score")
private Integer shuiScore;
@SerializedName("huo_score")
private Integer huoScore;
@SerializedName("tu_score")
private Integer tuScore;
@SerializedName("jin_score_percent")
private String jinScorePercent;
@SerializedName("mu_score_percent")
private String muScorePercent;
@SerializedName("shui_score_percent")
private String shuiScorePercent;
@SerializedName("huo_score_percent")
private String huoScorePercent;
@SerializedName("tu_score_percent")
private String tuScorePercent;
@SerializedName("yinyang")
private String yinyang;
}
}
@NoArgsConstructor
@Data
public static class DetailInfoDTO implements Serializable {
@SerializedName("dayun_info")
private List<DayunInfoDTO> dayunInfo;
@SerializedName("dayun_born_info")
private DayunInfoDTO dayunBornInfo;
@SerializedName("sizhu_info")
private SizhuInfoDTO sizhuInfo;
@SerializedName("taishen_info")
private TaishenInfoDTO taishenInfo;
@NoArgsConstructor
@Data
public static class SizhuInfoDTO implements Serializable {
@SerializedName("year")
private YearDTO year;
@SerializedName("month")
private MonthDTO month;
@SerializedName("day")
private DayDTO day;
@SerializedName("hour")
private HourDTO hour;
@NoArgsConstructor
@Data
public static class YearDTO implements Serializable {
@SerializedName("tg_god")
private String tgGod;
@SerializedName("tg")
private String tg;
@SerializedName("dz")
private String dz;
@SerializedName("cg")
private List<String> cg;
@SerializedName("dz_god")
private List<String> dzGod;
@SerializedName("dz_star_cs")
private String dzStarCs;
@SerializedName("dz_self_cs")
private String dzSelfCs;
@SerializedName("kw")
private String kw;
@SerializedName("ny")
private String ny;
@SerializedName("wx")
private String wx;
@SerializedName("xun")
private String xun;
@SerializedName("shensha")
private String shensha;
}
@NoArgsConstructor
@Data
public static class MonthDTO implements Serializable {
@SerializedName("tg_god")
private String tgGod;
@SerializedName("tg")
private String tg;
@SerializedName("dz")
private String dz;
@SerializedName("cg")
private List<String> cg;
@SerializedName("dz_god")
private List<String> dzGod;
@SerializedName("dz_star_cs")
private String dzStarCs;
@SerializedName("dz_self_cs")
private String dzSelfCs;
@SerializedName("kw")
private String kw;
@SerializedName("ny")
private String ny;
@SerializedName("wx")
private String wx;
@SerializedName("xun")
private String xun;
@SerializedName("shensha")
private String shensha;
}
@NoArgsConstructor
@Data
public static class DayDTO implements Serializable {
@SerializedName("tg_god")
private String tgGod;
@SerializedName("tg")
private String tg;
@SerializedName("dz")
private String dz;
@SerializedName("cg")
private List<String> cg;
@SerializedName("dz_god")
private List<String> dzGod;
@SerializedName("dz_star_cs")
private String dzStarCs;
@SerializedName("dz_self_cs")
private String dzSelfCs;
@SerializedName("kw")
private String kw;
@SerializedName("ny")
private String ny;
@SerializedName("wx")
private String wx;
@SerializedName("xun")
private String xun;
@SerializedName("shensha")
private String shensha;
}
@NoArgsConstructor
@Data
public static class HourDTO implements Serializable {
@SerializedName("tg_god")
private String tgGod;
@SerializedName("tg")
private String tg;
@SerializedName("dz")
private String dz;
@SerializedName("cg")
private List<String> cg;
@SerializedName("dz_god")
private List<String> dzGod;
@SerializedName("dz_star_cs")
private String dzStarCs;
@SerializedName("dz_self_cs")
private String dzSelfCs;
@SerializedName("kw")
private String kw;
@SerializedName("ny")
private String ny;
@SerializedName("wx")
private String wx;
@SerializedName("xun")
private String xun;
@SerializedName("shensha")
private String shensha;
}
}
@NoArgsConstructor
@Data
public static class TaishenInfoDTO implements Serializable {
@SerializedName("taiyuan")
private TaiyuanDTO taiyuan;
@SerializedName("taixi")
private TaixiDTO taixi;
@SerializedName("minggong")
private MinggongDTO minggong;
@SerializedName("shengong")
private ShengongDTO shengong;
@NoArgsConstructor
@Data
public static class TaiyuanDTO implements Serializable {
@SerializedName("ganzhi")
private String ganzhi;
@SerializedName("xun")
private String xun;
@SerializedName("kongwang")
private String kongwang;
@SerializedName("changsheng")
private String changsheng;
@SerializedName("gan")
private String gan;
@SerializedName("zhi")
private String zhi;
@SerializedName("dz_cg")
private List<String> dzCg;
@SerializedName("tg_god")
private String tgGod;
@SerializedName("dz_god")
private List<String> dzGod;
@SerializedName("dz_star_cs")
private String dzStarCs;
@SerializedName("dz_self_cs")
private String dzSelfCs;
@SerializedName("nayin")
private String nayin;
@SerializedName("wuxing")
private String wuxing;
@SerializedName("tg_liuyi")
private String tgLiuyi;
@SerializedName("dz_liuyi")
private String dzLiuyi;
@SerializedName("shensha")
private String shensha;
}
@NoArgsConstructor
@Data
public static class TaixiDTO implements Serializable {
@SerializedName("ganzhi")
private String ganzhi;
@SerializedName("xun")
private String xun;
@SerializedName("kongwang")
private String kongwang;
@SerializedName("changsheng")
private String changsheng;
@SerializedName("gan")
private String gan;
@SerializedName("zhi")
private String zhi;
@SerializedName("dz_cg")
private List<String> dzCg;
@SerializedName("tg_god")
private String tgGod;
@SerializedName("dz_god")
private List<String> dzGod;
@SerializedName("dz_star_cs")
private String dzStarCs;
@SerializedName("dz_self_cs")
private String dzSelfCs;
@SerializedName("nayin")
private String nayin;
@SerializedName("wuxing")
private String wuxing;
@SerializedName("tg_liuyi")
private String tgLiuyi;
@SerializedName("dz_liuyi")
private String dzLiuyi;
@SerializedName("shensha")
private String shensha;
}
@NoArgsConstructor
@Data
public static class MinggongDTO implements Serializable {
@SerializedName("ganzhi")
private String ganzhi;
@SerializedName("xun")
private String xun;
@SerializedName("kongwang")
private String kongwang;
@SerializedName("changsheng")
private String changsheng;
@SerializedName("gan")
private String gan;
@SerializedName("zhi")
private String zhi;
@SerializedName("dz_cg")
private List<String> dzCg;
@SerializedName("tg_god")
private String tgGod;
@SerializedName("dz_god")
private List<String> dzGod;
@SerializedName("dz_star_cs")
private String dzStarCs;
@SerializedName("dz_self_cs")
private String dzSelfCs;
@SerializedName("nayin")
private String nayin;
@SerializedName("wuxing")
private String wuxing;
@SerializedName("tg_liuyi")
private String tgLiuyi;
@SerializedName("dz_liuyi")
private String dzLiuyi;
@SerializedName("shensha")
private String shensha;
}
@NoArgsConstructor
@Data
public static class ShengongDTO implements Serializable {
@SerializedName("ganzhi")
private String ganzhi;
@SerializedName("xun")
private String xun;
@SerializedName("kongwang")
private String kongwang;
@SerializedName("changsheng")
private String changsheng;
@SerializedName("gan")
private String gan;
@SerializedName("zhi")
private String zhi;
@SerializedName("dz_cg")
private List<String> dzCg;
@SerializedName("tg_god")
private String tgGod;
@SerializedName("dz_god")
private List<String> dzGod;
@SerializedName("dz_star_cs")
private String dzStarCs;
@SerializedName("dz_self_cs")
private String dzSelfCs;
@SerializedName("nayin")
private String nayin;
@SerializedName("wuxing")
private String wuxing;
@SerializedName("tg_liuyi")
private String tgLiuyi;
@SerializedName("dz_liuyi")
private String dzLiuyi;
@SerializedName("shensha")
private String shensha;
}
}
@NoArgsConstructor
@Data
public static class DayunInfoDTO implements Serializable {
@SerializedName("dayun_is_tongxian")
private boolean isTongXian = false;
@SerializedName("dayun_tongxian")
private String dayunTongxian;
@SerializedName("dayun_index")
private Integer dayunIndex;
@SerializedName("dayun_start_year")
private Integer dayunStartYear;
@SerializedName("dayun_start_age")
private Integer dayunStartAge;
@SerializedName("dayun_end_year")
private Integer dayunEndYear;
@SerializedName("dayun_end_age")
private Integer dayunEndAge;
@SerializedName("dayun_start_ganzhi")
private String dayunStartGanzhi;
@SerializedName("dayun_xun")
private String dayunXun;
@SerializedName("dayun_kongwang")
private String dayunKongwang;
@SerializedName("dayun_shishen")
private String dayunShishen;
@SerializedName("dayun_changsheng")
private String dayunChangsheng;
@SerializedName("dayun_year_tg")
private String dayunYearTg;
@SerializedName("dayun_year_dz")
private String dayunYearDz;
@SerializedName("dayun_year_cg")
private List<String> dayunYearCg;
@SerializedName("dayun_year_tg_god")
private String dayunYearTgGod;
@SerializedName("dayun_year_dz_god")
private List<String> dayunYearDzGod;
@SerializedName("dayun_dz_star_cs")
private String dayunDzStarCs;
@SerializedName("dayun_dz_self_cs")
private String dayunDzSelfCs;
@SerializedName("dayun_nayin")
private String dayunNayin;
@SerializedName("dayun_wuxing")
private String dayunWuxing;
@SerializedName("dayun_tg_liuyi")
private String dayunTgLiuyi;
@SerializedName("dayun_dz_liuyi")
private String dayunDzLiuyi;
@SerializedName("liunian_info")
private List<LiunianInfoDTO> liunianInfo;
@SerializedName("xiaoyun_info")
private List<XiaoyunInfoDTO> xiaoyunInfo;
@SerializedName("dayun_shensha")
private String dayunShensha;
@NoArgsConstructor
@Data
public static class LiunianInfoDTO implements Serializable {
@SerializedName("liunian_index")
private Integer liunianIndex;
@SerializedName("liunian_year")
private Integer liunianYear;
@SerializedName("liunian_age")
private Integer liunianAge;
@SerializedName("liunian_ganzhi")
private String liunianGanzhi;
@SerializedName("liunian_xun")
private String liunianXun;
@SerializedName("liunian_kongwang")
private String liunianKongwang;
@SerializedName("liunian_shishen")
private String liunianShishen;
@SerializedName("liunian_changsheng")
private String liunianChangsheng;
@SerializedName("liunian_jieqi")
private List<LiunianJieqiDTO> liunianJieqi;
@SerializedName("liunian_year_tg")
private String liunianYearTg;
@SerializedName("liunian_year_dz")
private String liunianYearDz;
@SerializedName("liunian_year_cg")
private List<String> liunianYearCg;
@SerializedName("liunian_tg_god")
private String liunianTgGod;
@SerializedName("liunian_dz_god")
private List<String> liunianDzGod;
@SerializedName("liunian_dz_star_cs")
private String liunianDzStarCs;
@SerializedName("liunian_dz_self_cs")
private String liunianDzSelfCs;
@SerializedName("liunian_nayin")
private String liunianNayin;
@SerializedName("liunian_wuxing")
private String liunianWuxing;
@SerializedName("liunian_tg_liuyi")
private String liunianTgLiuyi;
@SerializedName("liunian_dz_liuyi")
private String liunianDzLiuyi;
@SerializedName("liunian_shensha")
private String liunianShensha;
@SerializedName("liuyue_info")
private List<LiuyueInfoDTO> liuyueInfo;
@NoArgsConstructor
@Data
public static class LiunianJieqiDTO implements Serializable {
@SerializedName("jieqi_name")
private String jieqiName;
@SerializedName("jieqi_solar_ymdhms")
private String jieqiSolarYmdhms;
@SerializedName("jieqi_lunar_ymdhms_isleap")
private String jieqiLunarYmdhmsIsleap;
@SerializedName("jieqi_lunar_ymdhms")
private String jieqiLunarYmdhms;
}
@NoArgsConstructor
@Data
public static class LiuyueInfoDTO implements Serializable {
@SerializedName("liuyue_index")
private Integer liuyueIndex;
@SerializedName("liuyue_month")
private String liuyueMonth;
@SerializedName("liuyue_ganzhi")
private String liuyueGanzhi;
@SerializedName("liuyue_xun")
private String liuyueXun;
@SerializedName("liuyue_kongwang")
private String liuyueKongwang;
@SerializedName("liuyue_shishen")
private String liuyueShishen;
@SerializedName("liuyue_changsheng")
private String liuyueChangsheng;
@SerializedName("liuyue_month_tg")
private String liuyueMonthTg;
@SerializedName("liuyue_month_dz")
private String liuyueMonthDz;
@SerializedName("liuyue_month_cg")
private List<String> liuyueMonthCg;
@SerializedName("liuyue_month_tg_god")
private String liuyueMonthTgGod;
@SerializedName("liuyue_month_dz_god")
private List<String> liuyueMonthDzGod;
@SerializedName("liuyue_dz_star_cs")
private String liuyueDzStarCs;
@SerializedName("liuyue_dz_self_cs")
private String liuyueDzSelfCs;
@SerializedName("liuyue_nayin")
private String liuyueNayin;
@SerializedName("liuyue_wuxing")
private String liuyueWuxing;
@SerializedName("liuyue_tg_liuyi")
private String liuyueTgLiuyi;
@SerializedName("liuyue_dz_liuyi")
private String liuyueDzLiuyi;
@SerializedName("liuyue_shensha")
private String liuyueShensha;
}
}
@NoArgsConstructor
@Data
public static class XiaoyunInfoDTO implements Serializable {
@SerializedName("xiaoyun_index")
private Integer xiaoyunIndex;
@SerializedName("xiaoyun_year")
private Integer xiaoyunYear;
@SerializedName("xiaoyun_age")
private Integer xiaoyunAge;
@SerializedName("xiaoyun_ganzhi")
private String xiaoyunGanzhi;
@SerializedName("xiaoyun_xun")
private String xiaoyunXun;
@SerializedName("xiaoyun_kongwang")
private String xiaoyunKongwang;
@SerializedName("xiaoyun_shishen")
private String xiaoyunShishen;
@SerializedName("xiaoyun_changsheng")
private String xiaoyunChangsheng;
@SerializedName("xiaoyun_year_tg")
private String xiaoyunYearTg;
@SerializedName("xiaoyun_year_dz")
private String xiaoyunYearDz;
@SerializedName("xiaoyun_year_cg")
private List<String> xiaoyunYearCg;
@SerializedName("xiaoyun_tg_god")
private String xiaoyunTgGod;
@SerializedName("xiaoyun_dz_god")
private List<String> xiaoyunDzGod;
@SerializedName("xiaoyun_dz_star_cs")
private String xiaoyunDzStarCs;
@SerializedName("xiaoyun_dz_self_cs")
private String xiaoyunDzSelfCs;
@SerializedName("xiaoyun_nayin")
private String xiaoyunNayin;
@SerializedName("xiaoyun_wuxing")
private String xiaoyunWuxing;
@SerializedName("xiaoyun_tg_liuyi")
private String xiaoyunTgLiuyi;
@SerializedName("xiaoyun_dz_liuyi")
private String xiaoyunDzLiuyi;
@SerializedName("xiaoyun_shensha")
private String xiaoyunShensha;
}
}
}
}

View File

@@ -1,62 +0,0 @@
package com.ckkj.water.plate.entity;
import com.google.gson.annotations.SerializedName;
import java.io.Serializable;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @author fengxiaoyang
* @date 2025/8/11
* @description TODO: 描述该类的作用
*/
@NoArgsConstructor
@Data
public class BaziSaveSuccessEntity implements Serializable {
@SerializedName("recordId")
private String recordId;
@SerializedName("savedData")
private SavedDataDTO savedData;
@SerializedName("message")
private String message;
@SerializedName("saveTime")
private String saveTime;
@NoArgsConstructor
@Data
public static class SavedDataDTO {
@SerializedName("recordId")
private String recordId;
@SerializedName("birthPlace")
private String birthPlace;
@SerializedName("gender")
private String gender;
@SerializedName("yinLiBirthTime")
private String yinLiBirthTime;
@SerializedName("siZhu")
private SiZhuDTO siZhu;
@SerializedName("name")
private String name;
@SerializedName("yangLiBirthTime")
private String yangLiBirthTime;
@SerializedName("openSolarTime")
private String openSolarTime;
@NoArgsConstructor
@Data
public static class SiZhuDTO {
@SerializedName("yueZhu")
private String yueZhu;
@SerializedName("shiZhu")
private String shiZhu;
@SerializedName("riZhu")
private String riZhu;
@SerializedName("nianZhu")
private String nianZhu;
}
}
}

View File

@@ -1,17 +0,0 @@
package com.ckkj.water.plate.entity;
public class PaipanCache {
private static BaziResultBean cachedResult;
public static void set(BaziResultBean result) {
cachedResult = result;
}
public static BaziResultBean get() {
return cachedResult;
}
public static void clear() {
cachedResult = null;
}
}

View File

@@ -1,76 +0,0 @@
package com.ckkj.water.plate.entity;
import com.google.gson.annotations.SerializedName;
import java.io.Serializable;
import java.util.List;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @author fengxiaoyang
* @date 2025/8/9
* @description TODO: 描述该类的作用
*/
@NoArgsConstructor
@Data
public class PaipanHistoryEntity implements Serializable {
@SerializedName("total")
private Integer total;
@SerializedName("pages")
private Integer pages;
@SerializedName("records")
private List<RecordsDTO> records;
@SerializedName("hasNextPage")
private Boolean hasNextPage;
@SerializedName("pageSize")
private Integer pageSize;
@SerializedName("hasPreviousPage")
private Boolean hasPreviousPage;
@SerializedName("userId")
private Long userId;
@SerializedName("pageNum")
private Integer pageNum;
@NoArgsConstructor
@Data
public static class RecordsDTO implements Serializable{
@SerializedName("id")
private String id;
@SerializedName("userId")
private Long userId;
@SerializedName("name")
private String name;
@SerializedName("gender")
private String gender;
@SerializedName("birthType")
private String birthType;
@SerializedName("yangLiBirthTime")
private String yangLiBirthTime;
@SerializedName("yinLiBirthTime")
private String yinLiBirthTime;
@SerializedName("birthPlace")
private String birthPlace;
@SerializedName("openSolarTime")
private String openSolarTime;
@SerializedName("nianZhu")
private String nianZhu;
@SerializedName("yueZhu")
private String yueZhu;
@SerializedName("riZhu")
private String riZhu;
@SerializedName("shiZhu")
private String shiZhu;
@SerializedName("apiStatus")
private Integer apiStatus;
@SerializedName("apiMessage")
private String apiMessage;
@SerializedName("requestIp")
private String requestIp;
@SerializedName("remark")
private Object remark;
}
}

View File

@@ -1,63 +0,0 @@
package com.ckkj.water.plate.mvp;
import com.ckkj.water.base.IView;
import com.ckkj.water.network.BaseBean;
import com.ckkj.water.plate.entity.BaziResultBean;
import com.ckkj.water.plate.entity.BaziSaveSuccessEntity;
import com.ckkj.water.plate.entity.PaipanHistoryEntity;
import org.json.JSONObject;
import java.util.Map;
/**
* @author fengxiaoyang
* @date 2025/7/30
* @description TODO: 描述该类的作用
*/
public class PlateContract {
public interface CallBack<T> {
void success(T msg);
void fail(String msg);
}
public interface DataModel{
//保存八字排盘结果
void saveUserBirthInfo(JSONObject json, CallBack callBack);
//开始排盘
void startPaiPanByYfjApi(Map<String,Object> map , CallBack callBack);
//获取排盘结果
void getPaipanHistoryList(Map<String,Object> map, CallBack callBack);
//删除记录
void deleteRecordByID(Map<String,Object> map, CallBack callBack);
//根据八字排盘结果ai 解析
void aiParseBaziResult(JSONObject json, CallBack callBack);
//发送消息给 AI
void sendMsgToAi(JSONObject json, AiStreamCallback callBack);
}
public interface AiStreamCallback {
void onMessage(String messageChunk); // 每次返回一段内容
void onError(String error);
void onComplete(String complateContent); // 结束
void onSessionReceived(String sessionId); // 新增接收sessionId
void loginLost();
}
public interface PlateView extends IView {
//排盘成功
void getPaipanResult(BaziResultBean bean);
//保存八字成功
void saveBaziResultSuccess(BaziSaveSuccessEntity bean);
//历史记录
void getHistorySuccess(PaipanHistoryEntity entity);
//删除成功
void deletePaipanHistorySuccess(int pos);
// 新增流式回调方法
void onStreamMessageReceived(String messageChunk);
//完成
void onStreamComplete(String complateMsg);
//提交举报完成
void commitReportSuccess(BaseBean bean);
}
}

View File

@@ -1,424 +0,0 @@
package com.ckkj.water.plate.mvp;
import static android.content.ContentValues.TAG;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import com.ckkj.water.AppConfig;
import com.ckkj.water.network.BaseBean;
import com.ckkj.water.network.BaseYfjApiBean;
import com.ckkj.water.network.NetWorkManager;
import com.ckkj.water.plate.entity.BaziResultBean;
import com.ckkj.water.plate.entity.BaziSaveSuccessEntity;
import com.ckkj.water.plate.entity.PaipanHistoryEntity;
import org.json.JSONObject;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
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;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import org.json.JSONException;
/**
* @author fengxiaoyang
* @date 2025/7/30
* @description TODO: 描述该类的作用
*/
public class PlateImpl implements PlateContract.DataModel{
/**
* 保存八字排盘记录
* @param json
* @param callBack
*/
@Override
public void saveUserBirthInfo(JSONObject json, PlateContract.CallBack callBack) {
try {
NetWorkManager.getRequest().startPaipan(NetWorkManager.getToken(), NetWorkManager.toRequestBody(json))
.subscribeOn(Schedulers.io())
.unsubscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<BaseBean<BaziSaveSuccessEntity>>() {
@Override
public void onSubscribe(@NonNull Disposable d) {
}
@Override
public void onNext(@NonNull BaseBean<BaziSaveSuccessEntity> 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();
}
}
/**
* 排盘数据,调用三方 api
* @param map
* @param callBack
*/
@Override
public void startPaiPanByYfjApi(Map<String, Object> map, PlateContract.CallBack callBack) {
try {
// 使用getNoBaseUrlRequest()调用第三方API因为API URL是完整的
NetWorkManager.getNoBaseUrlRequest().startPaipanByYfj(NetWorkManager.getToken(), map)
.subscribeOn(Schedulers.io())
.unsubscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<BaseYfjApiBean<BaziResultBean>>() {
@Override
public void onSubscribe(@NonNull Disposable d) {
}
@Override
public void onNext(@NonNull BaseYfjApiBean<BaziResultBean> bean) {
if (bean.getErrcode() == 0) {
// 成功返回数据
callBack.success(bean.getData());
} else {
// API返回错误
callBack.fail(bean.getErrmsg());
}
}
@Override
public void onError(@NonNull Throwable e) {
callBack.fail(e.getMessage());
}
@Override
public void onComplete() {
}
});
} catch (Exception e) {
e.printStackTrace();
callBack.fail(e.getMessage());
}
}
/**
* 排盘历史记录
* @param map
* @param callBack
*/
@Override
public void getPaipanHistoryList(Map<String, Object> map, PlateContract.CallBack callBack) {
try {
NetWorkManager.getRequest().getPaipanHistoryList(NetWorkManager.getToken())
.subscribeOn(Schedulers.io())
.unsubscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<BaseBean<PaipanHistoryEntity>>() {
@Override
public void onSubscribe(@NonNull Disposable d) {
}
@Override
public void onNext(@NonNull BaseBean<PaipanHistoryEntity> 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();
}
}
/**
* 删除记录
* @param map
* @param callBack
*/
@Override
public void deleteRecordByID(Map<String, Object> map, PlateContract.CallBack callBack) {
try {
NetWorkManager.getRequest().deletePaipanRecordById(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);
}else{
callBack.fail(bean.getMessage());
}
}
@Override
public void onError(@NonNull Throwable e) {
callBack.fail(e.getMessage());
}
@Override
public void onComplete() {
}
});
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* 八字排盘结果AI 解析
* @param json
* @param callBack
*/
@Override
public void aiParseBaziResult(JSONObject json, PlateContract.CallBack callBack) {
try {
NetWorkManager.getRequest().aiParesBaziResult(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());
} 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();
}
}
/**
* AI解盘
* @param json
* @param callBack
*/
private final OkHttpClient client = new OkHttpClient();
private Call currentCall = null; // 新增保存当前请求的Call对象
private volatile boolean isRequestStopped = false; // 新增:标记是否已停止请求
@Override
public void sendMsgToAi(JSONObject json, PlateContract.AiStreamCallback callBack) {
try {
String finalUrl = AppConfig.BASE_URL + "mobile/paiPan/ai";
Log.d(TAG, "Request URL: " + finalUrl);
Request request = new Request.Builder()
.addHeader("Authorization", "Bearer " + AppConfig.USER_TOKEN)
.post(NetWorkManager.toRequestBody(json))
.url(finalUrl)
.build();
currentCall = client.newCall(request);
isRequestStopped = false;
currentCall.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
if (isRequestStopped) return; // 如果已停止,不处理失败回调
new Handler(Looper.getMainLooper()).post(() -> {
if (callBack != null) callBack.onError(e.getMessage());
});
}
@Override
public void onResponse(Call call, Response response) {
if (isRequestStopped) return;
if (!response.isSuccessful()) {
new Handler(Looper.getMainLooper()).post(() -> {
if (callBack != null) callBack.onError("请求失败: " + response.code());
});
return;
}
InputStream inputStream = response.body().byteStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
try {
// 处理SSE流式数据
handleSSEStream(reader, callBack);
} catch (Exception e) {
new Handler(Looper.getMainLooper()).post(() -> {
if (callBack != null) callBack.onError("解析异常: " + e.getMessage());
});
} finally {
try {
reader.close();
response.close();
} catch (IOException ignored) {}
}
}
});
} catch (Exception e) {
new Handler(Looper.getMainLooper()).post(() -> {
if (callBack != null) callBack.onError("请求异常: " + e.getMessage());
});
}
}
/**
* 处理SSE流式数据
*/
private void handleSSEStream(BufferedReader reader, PlateContract.AiStreamCallback callBack) throws IOException {
String line;
StringBuilder currentEvent = new StringBuilder();
String currentEventType = null;
while ((line = reader.readLine()) != null && !isRequestStopped) {
if (line.trim().isEmpty()) {
// 空行表示一个事件结束,处理当前事件
if (currentEventType != null && currentEvent.length() > 0) {
processEvent(currentEventType, currentEvent.toString(), callBack);
currentEvent.setLength(0);
currentEventType = null;
}
} else if (line.startsWith("event:")) {
// 事件类型
currentEventType = line.substring(6).trim();
} else if (line.startsWith("data:")) {
// 事件数据
String data = line.substring(5).trim();
currentEvent.append(data);
}
}
// 处理最后一个事件
if (currentEventType != null && currentEvent.length() > 0) {
processEvent(currentEventType, currentEvent.toString(), callBack);
}
}
/**
* 处理单个事件
*/
private void processEvent(String eventType, String data, PlateContract.AiStreamCallback callBack) {
new Handler(Looper.getMainLooper()).post(() -> {
try {
switch (eventType) {
case "start":
// 开始事件,可以在这里做一些初始化
Log.d(TAG, "AI解盘开始: " + data);
break;
case "paiPanInfo":
// 排盘信息事件
Log.d(TAG, "排盘信息: " + data);
break;
case "api-info":
// API信息事件
Log.d(TAG, "API信息: " + data);
break;
case "chunk":
// 内容块事件,这是主要的文本内容
try {
JSONObject chunkData = new JSONObject(data);
String content = chunkData.optString("content", "");
boolean hasNewline = chunkData.optBoolean("hasNewline", false);
boolean isMarkdown = chunkData.optBoolean("isMarkdown", false);
// 发送内容块到回调
if (callBack != null && !content.isEmpty()) {
callBack.onMessage(content);
}
} catch (JSONException e) {
Log.e(TAG, "解析chunk数据失败: " + e.getMessage());
}
break;
case "request-id":
// 请求ID事件
Log.d(TAG, "请求ID: " + data);
break;
case "complete":
// 完成事件
Log.d(TAG, "AI解盘完成: " + data);
if (callBack != null) {
callBack.onComplete(data);
}
break;
default:
Log.d(TAG, "未知事件类型: " + eventType + ", 数据: " + data);
break;
}
} catch (Exception e) {
Log.e(TAG, "处理事件失败: " + e.getMessage());
}
});
}
/**
* 停止当前请求
*/
public void stopCurrentRequest() {
isRequestStopped = true;
if (currentCall != null && !currentCall.isCanceled()) {
currentCall.cancel();
currentCall = null;
}
}
}

View File

@@ -1,225 +0,0 @@
//package com.ckkj.water.plate.mvp;
//
//import com.ckkj.water.base.BasePresenter;
//import com.ckkj.water.network.BaseBean;
//import com.ckkj.water.plate.entity.BaziResultBean;
//import com.ckkj.water.plate.entity.BaziSaveSuccessEntity;
//import com.ckkj.water.plate.entity.PaipanHistoryEntity;
//
//import org.json.JSONException;
//import org.json.JSONObject;
//
//import java.util.HashMap;
//import java.util.Map;
//
///**
// * @author fengxiaoyang
// * @date 2025/7/30
// * @description TODO: 描述该类的作用
// */
//
//public class PlatePresenter extends BasePresenter<PlateContract.PlateView> {
// private PlateImpl impl;
//
// public PlatePresenter(PlateImpl impl) {
// this.impl = impl;
// }
//
// /**
// * 排盘,直接调用缘份居 Api
// * @param map
// */
// public void startPaiPan(Map<String, Object> map) {
// impl.startPaiPanByYfjApi(map, new PlateContract.CallBack<BaziResultBean>() {
// @Override
// public void success(BaziResultBean entity) {
// if(PlatePresenter.this.getView() != null){
// if(PlatePresenter.this.getView() != null){
// PlatePresenter.this.getView().getPaipanResult(entity);
// }
// }
// }
//
// @Override
// public void fail(String msg) {
// if(PlatePresenter.this.getView() != null){
// PlatePresenter.this.getView().showError(msg);
// }
// }
// });
// }
//
// /**
// * 上传八字结果
// *
// * @param result
// * @param cityData
// * @param timeType
// */
// public void uploadBaziResult(BaziResultBean result, CityDataEntity cityData, int timeType) {
// try {
// BaziResultBean.BaseInfoDTO baseInfoDTO = result.getBaseInfo();
// BaziResultBean.DetailInfoDTO.SizhuInfoDTO sizhuInfoDTO = result.getDetailInfo().getSizhuInfo();
// JSONObject json = new JSONObject();
// json.put("name",baseInfoDTO.getName());
// json.put("gender",baseInfoDTO.getSex().equals("乾造")? "0" : "1");
// json.put("birthType",timeType == 2001 ? "1":"0");
// json.put("yangLiBirthTime",baseInfoDTO.getGongli());
// json.put("yinLiBirthTime",baseInfoDTO.getNongli());
// json.put("birthPlace",cityData == null ? "北京市": cityData.getCityName());
// json.put("province",cityData == null ? "北京市": cityData.getProvinceName());
// json.put("city",cityData == null ? "北京": cityData.getCityName());
// json.put("openSolarTime","2");
// json.put("nianZhu",sizhuInfoDTO.getYear().getTg() + "," + sizhuInfoDTO.getYear().getDz());
// json.put("yueZhu",sizhuInfoDTO.getMonth().getTg() + "," + sizhuInfoDTO.getMonth().getDz());
// json.put("riZhu",sizhuInfoDTO.getDay().getTg() + "," + sizhuInfoDTO.getDay().getDz());
// json.put("shiZhu",sizhuInfoDTO.getHour().getTg() + "," + sizhuInfoDTO.getHour().getDz());
// impl.saveUserBirthInfo(json, new PlateContract.CallBack<BaziSaveSuccessEntity>() {
// @Override
// public void success(BaziSaveSuccessEntity bean) {
// if(PlatePresenter.this.getView() != null){
// if(PlatePresenter.this.getView() != null){
// PlatePresenter.this.getView().saveBaziResultSuccess(bean);
// }
// }
// }
//
// @Override
// public void fail(String msg) {
// if(PlatePresenter.this.getView() != null){
// if(PlatePresenter.this.getView() != null){
// PlatePresenter.this.getView().showError(msg);
// }
// }
// }
// });
// } catch (JSONException e) {
// throw new RuntimeException(e);
// }
// }
//
// /**
// * 获取历史运势
// * @param page
// */
// public void getHistoryDatas(int page) {
// Map<String, Object> map = new HashMap<>();
// map.put("pageNum", page);
// map.put("pageSize", 10);
// impl.getPaipanHistoryList(map, new PlateContract.CallBack<PaipanHistoryEntity>() {
//
// @Override
// public void success(PaipanHistoryEntity entity) {
// if(PlatePresenter.this.getView() != null){
// PlatePresenter.this.getView().getHistorySuccess(entity);
// }
// }
//
// @Override
// public void fail(String msg) {
// if(PlatePresenter.this.getView() != null){
// PlatePresenter.this.getView().showError(msg);
// }
// }
// });
// }
//
// /**
// * 删除记录
// * @param id
// */
// public void deleteRecordByID(String id,int pos) {
// Map<String, Object> map = new HashMap<>();
// map.put("recordId", id);
// impl.deleteRecordByID(map, new PlateContract.CallBack<BaseBean>() {
// @Override
// public void success(BaseBean bean) {
// if(PlatePresenter.this.getView() != null){
// PlatePresenter.this.getView().deletePaipanHistorySuccess(pos);
// }
// }
//
// @Override
// public void fail(String msg) {
// if(PlatePresenter.this.getView() != null){
// PlatePresenter.this.getView().showError(msg);
// }
// }
// });
// }
//
// /**
// * ai 分析八字
// * @param mSaveEntity
// */
// public void AiParseBaziResult(BaziSaveSuccessEntity mSaveEntity) {
// try {
// JSONObject json = new JSONObject();
// json.put("resultId", mSaveEntity.getRecordId());
// impl.sendMsgToAi(json, new PlateContract.AiStreamCallback() {
// @Override
// public void onMessage(String messageChunk) {
// if (PlatePresenter.this.getView() != null) {
// PlatePresenter.this.getView().onStreamMessageReceived(messageChunk);
// }
// }
//
// @Override
// public void onError(String error) {
// if (PlatePresenter.this.getView() != null) {
// PlatePresenter.this.getView().showError(error);
// }
// }
//
// @Override
// public void onComplete(String complateContent) {
// if (PlatePresenter.this.getView() != null) {
// PlatePresenter.this.getView().onStreamComplete(complateContent);
// }
// }
//
// @Override
// public void onSessionReceived(String sessionId) {
// // 这个回调在当前场景下可能不需要,但保留接口一致性
// // Log.d("PlatePresenter", "Session received: " + sessionId);
// }
//
// @Override
// public void loginLost() {
// if (PlatePresenter.this.getView() != null) {
// // 处理登录失效的情况
// // 这里可以根据需要跳转到登录页面
// // Log.w("PlatePresenter", "Login lost");
// }
// }
// });
// } catch (JSONException e) {
// throw new RuntimeException(e);
// }
// }
//
//
// /**
// * 举报
// * @param reason
// */
// public void commitReport(String reason) {
// Map<String, Object> map = new HashMap<>();
// map.put("content", reason);
// new IndexImpl().commitReport(map, new IndexContract.CallBack<BaseBean>() {
// @Override
// public void success(BaseBean bean) {
// if (PlatePresenter.this.getView() != null) {
// PlatePresenter.this.getView().commitReportSuccess(bean);
// }
// }
//
// @Override
// public void fail(String msg) {
// if (PlatePresenter.this.getView() != null) {
// PlatePresenter.this.getView().showError(msg);
// }
// }
// });
// }
//}

View File

@@ -2,7 +2,7 @@ package com.ckkj.water.utils;
import android.util.Log;
public class ClickUtils {
public class FastClickUtils {
/**
* Android优雅地处理按钮重复点击的几种方法

View File

@@ -4,8 +4,7 @@ import android.content.Context;
import com.ckkj.water.AppConfig;
import com.ckkj.water.ConstantUtil;
import com.ckkj.water.base.entity.MineUserInfoBean;
import com.ckkj.water.base.entity.UserInfoEntity;
import com.ckkj.water.mine.entity.MineUserInfoBean;
import com.ckkj.water.login.entity.LoginEntity;
import com.ckkj.water.utils.dataUtil.SharePreUtil;

View File

@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
android:oneshot="false">
<item
android:drawable="@mipmap/img_add_dev_aini_1"
android:duration="300" />
<item
android:drawable="@mipmap/img_add_dev_aini_2"
android:duration="300" />
<item
android:drawable="@mipmap/img_add_dev_aini_3"
android:duration="300" />
<item
android:drawable="@mipmap/img_add_dev_aini_2"
android:duration="500" />
</animation-list>

View File

@@ -1,33 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
android:oneshot="false">
<item
android:drawable="@mipmap/img_add_dev_aini_1"
android:duration="200" />
<item
android:drawable="@mipmap/img_add_dev_aini_2"
android:duration="200" />
<item
android:drawable="@mipmap/img_add_dev_aini_3"
android:duration="200" />
<item
android:drawable="@mipmap/img_add_dev_aini_2"
android:duration="500" />
<item
android:drawable="@mipmap/img_connect_anim_phone1"
android:duration="200" />
<item
android:drawable="@mipmap/img_connect_anim_phone2"
android:duration="200" />
<item
android:drawable="@mipmap/img_connect_anim_phone3"
android:duration="200" />
<item
android:drawable="@mipmap/img_connect_anim_phone1"
android:duration="500" />
<item
android:drawable="@mipmap/img_connect_anim_wifi1"

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