From b7ab2e69a4e1381141a35b8b3b8ad2218191dfdd Mon Sep 17 00:00:00 2001
From: fengjignqi <15192412330@163.com>
Date: Mon, 1 Jun 2026 15:54:06 +0800
Subject: [PATCH] =?UTF-8?q?=E6=8E=92=E7=A8=8B=E6=B5=87=E6=B0=B4=E5=8E=86?=
=?UTF-8?q?=E5=8F=B2=E8=AE=B0=E5=BD=95?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
app/build.gradle | 3 +-
app/src/main/AndroidManifest.xml | 4 +
.../com/ckkj/water/base/BaseActivity.java | 90 +++-
.../water/device/AddDeviceActivity_copy.java | 489 ++++++++++++++++++
.../water/device/DeviceControlActivity.java | 108 +++-
.../water/device/DeviceSettingsActivity.java | 4 +-
.../adapter/DeviceTimeSelectAdapter.java | 11 +-
.../com/ckkj/water/device/mvp/DeviceImpl.java | 35 ++
.../water/device/mvp/DevicePresenter.java | 33 ++
.../ckkj/water/history/HistoryFragment.java | 6 +
.../water/history/TabHistoryFragment.java | 78 ++-
.../adapter/WateringHistoryAdapter.java | 4 +-
.../water/history/entity/WateringRecord.java | 25 +-
.../water/history/mvp/HistoryContract.java | 6 +-
.../ckkj/water/history/mvp/HistoryImpl.java | 8 +-
.../water/history/mvp/HistoryPresenter.java | 11 +-
.../water/mine/MineInfomationActivity.java | 4 +-
.../java/com/ckkj/water/network/Request.java | 8 +-
app/src/main/res/layout/add_device_layout.xml | 13 +
.../main/res/layout/device_control_layout.xml | 4 +-
.../layout/tab_history_fragment_layout.xml | 43 +-
21 files changed, 953 insertions(+), 34 deletions(-)
create mode 100644 app/src/main/java/com/ckkj/water/device/AddDeviceActivity_copy.java
diff --git a/app/build.gradle b/app/build.gradle
index 01d7a8f..64b68ec 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -226,7 +226,8 @@ dependencies {
implementation "androidx.camera:camera-camera2:1.0.2"
implementation "androidx.camera:camera-lifecycle:1.0.2"
implementation "androidx.camera:camera-view:1.0.0-alpha25"
- //蓝牙管理
+ implementation 'no.nordicsemi.android.support.v18:scanner:1.6.0'
+ //蓝牙通讯
implementation 'no.nordicsemi.android:ble:2.11.0'
}
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 3f2b678..6c514b9 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -164,6 +164,10 @@
android:name="com.ckkj.water.device.AddDeviceActivity"
android:screenOrientation="portrait"
android:windowSoftInputMode="adjustResize"/>
+
public static final int REQUEST_EVENT_CODE_10001 = 10001;
public static final int REQUEST_EVENT_CODE_10002 = 10002;
public static final int REQUEST_EVENT_CODE_10003 = 10003;
+ public static final int INPUT_TYPE_NORMAL = 0; // 默认
+ public static final int INPUT_TYPE_NUMBER = 1; // 数字
+ public static final int INPUT_TYPE_LETTER = 2; // 英文字母
+ public static final int INPUT_TYPE_CHINESE = 3; // 中文
+ public static final int INPUT_TYPE_NUMBER_LETTER = 4;//数字+字母
public InputFilter mInputFilter;
private static final AtomicBoolean isDialogShown = new AtomicBoolean(false); // 使用 AtomicBoolean 保证线程安全
private ObjectAnimator rotateAnimator;
@@ -484,15 +490,29 @@ public abstract class BaseActivity
* @param confirmText 确定 文案
* @param click
*/
- public void showEditDialog(String title, String hint,String content, boolean touchOutsideCancel, String cancelText, String confirmText,
+ public void showEditDialog(String title,
+ String hint,
+ String content,
+ boolean touchOutsideCancel,
+ String cancelText,
+ String confirmText,
+ int inputType,
final OnDialogClick click) {
View view = getLayoutInflater().inflate(R.layout.public_dialog_input_text, null);
EditText editText = view.findViewById(R.id.et_input);
+ // EditText自动获取焦点
+ editText.requestFocus();
+ //设置输入类型
+ setEditInputType(editText,inputType);
+
if(TextUtils.isEmpty(content)){
editText.setHint(hint);
}else{
editText.setText(content);
}
+ if (!TextUtils.isEmpty(content)) {
+ editText.setSelection(editText.getText().length());
+ }
setTextView(R.id.tv_title, title, view);
if (!TextUtils.isEmpty(confirmText) && !TextUtils.isEmpty(cancelText)) {
((TextView) view.findViewById(R.id.btnLeft)).setText(cancelText);
@@ -1128,4 +1148,72 @@ public abstract class BaseActivity
// 方法2:通过Application检查(如果有记录当前Activity)
return MyApplication.getCurrentActivity() == this;
}
+
+ private void setEditInputType(EditText editText,int type){
+
+ switch (type){
+
+ case INPUT_TYPE_NUMBER:
+ //纯数字键盘
+ editText.setInputType(
+ InputType.TYPE_CLASS_NUMBER
+ );
+ break;
+
+ case INPUT_TYPE_LETTER:
+
+ //只能输入字母
+ editText.setFilters(
+ new InputFilter[]{
+ (source,start,end,dest,dstart,dend)->{
+
+ if(source.toString()
+ .matches("[a-zA-Z]+")){
+ return source;
+ }
+ return "";
+ }
+ });
+ break;
+
+ case INPUT_TYPE_CHINESE:
+
+ //只能输入中文
+ editText.setFilters(
+ new InputFilter[]{
+ (source,start,end,dest,dstart,dend)->{
+
+ if(source.toString()
+ .matches("[\\u4e00-\\u9fa5]+")){
+ return source;
+ }
+ return "";
+ }
+ });
+ break;
+
+ case INPUT_TYPE_NUMBER_LETTER:
+
+ //数字+字母
+ editText.setFilters(
+ new InputFilter[]{
+ (source,start,end,dest,dstart,dend)->{
+
+ if(source.toString()
+ .matches("[a-zA-Z0-9]+")){
+ return source;
+ }
+ return "";
+ }
+ });
+ break;
+
+ default:
+ editText.setInputType(
+ InputType.TYPE_CLASS_TEXT
+ );
+ break;
+ }
+
+ }
}
diff --git a/app/src/main/java/com/ckkj/water/device/AddDeviceActivity_copy.java b/app/src/main/java/com/ckkj/water/device/AddDeviceActivity_copy.java
new file mode 100644
index 0000000..d22a501
--- /dev/null
+++ b/app/src/main/java/com/ckkj/water/device/AddDeviceActivity_copy.java
@@ -0,0 +1,489 @@
+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.view.View;
+import android.widget.ImageView;
+
+import androidx.annotation.NonNull;
+import androidx.appcompat.app.AlertDialog;
+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.databinding.AddDeviceLayoutBinding;
+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.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.ArrayList;
+import java.util.List;
+import java.util.Set;
+
+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.ScanResult;
+import no.nordicsemi.android.support.v18.scanner.ScanSettings;
+import pub.devrel.easypermissions.EasyPermissions;
+
+/**
+ * 添加设备页面
+ */
+public class AddDeviceActivity_copy extends BaseActivity
+ 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 discoveredDevices = new ArrayList<>();
+ private AlertDialog deviceListDialog;
+
+ @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);
+ if(checkBluetoothPermissions()){
+ // 初始化蓝牙适配器
+ initBluetooth();
+ BluetoothLeScannerCompat scanner = BluetoothLeScannerCompat.getScanner();
+ ScanSettings settings = new ScanSettings.Builder()
+ .setLegacy(false)
+ .setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY)
+ .setReportDelay(5000)
+ .setUseHardwareBatchingIfSupported(true)
+ .build();
+ List filters = new ArrayList<>();
+ scanner.startScan(null, settings, new ScanCallback() {
+ @Override
+ public void onScanResult(int callbackType, @NonNull ScanResult result) {
+ super.onScanResult(callbackType, result);
+
+ }
+
+ @Override
+ public void onBatchScanResults(@NonNull List results) {
+ super.onBatchScanResults(results);
+ if(results != null){
+ int a = 0;
+ }
+ }
+
+ @Override
+ public void onScanFailed(int errorCode) {
+ super.onScanFailed(errorCode);
+ }
+ });
+ }
+
+
+ // 启动帧动画
+ ImageView ivScanAnimation = viewBinding.ivScanAnimation;
+ if (ivScanAnimation.getDrawable() instanceof AnimationDrawable) {
+ AnimationDrawable animationDrawable = (AnimationDrawable) ivScanAnimation.getDrawable();
+ animationDrawable.start();
+ }
+ new Handler().postDelayed(new Runnable() {
+ @Override
+ public void run() {
+ // 停止帧动画
+ ImageView ivScanAnimation = viewBinding.ivScanAnimation;
+ if (ivScanAnimation.getDrawable() instanceof AnimationDrawable) {
+ AnimationDrawable animationDrawable = (AnimationDrawable) ivScanAnimation.getDrawable();
+ if (animationDrawable.isRunning()) {
+ animationDrawable.stop();
+ viewBinding.ivScanAnimation.setVisibility(GONE);
+ viewBinding.imgDeviceItem.setVisibility(VISIBLE);
+ }
+ }
+ }
+ },3000);
+ initListener();
+ }
+
+ /**
+ * 初始化蓝牙适配器
+ */
+ private void initBluetooth() {
+ BluetoothManager bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
+ if (bluetoothManager != null) {
+ bluetoothAdapter = bluetoothManager.getAdapter();
+ }
+
+ if (bluetoothAdapter == null) {
+ ToastUtil.showShort(mContext, "设备不支持蓝牙");
+ return;
+ }
+
+ // 检查蓝牙是否开启
+ if (!bluetoothAdapter.isEnabled()) {
+ Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
+ startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
+ }
+ }
+
+ /**
+ * 检查蓝牙权限
+ */
+ 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 startBleScan() {
+ if (bluetoothAdapter == null || !bluetoothAdapter.isEnabled()) {
+ ToastUtil.showShort(mContext, "请先开启蓝牙");
+ return;
+ }
+
+ if (!checkBluetoothPermissions()) {
+ return;
+ }
+
+ discoveredDevices.clear();
+ showLoadingDialog();
+
+ // 获取已配对设备
+ Set pairedDevices = bluetoothAdapter.getBondedDevices();
+ if (pairedDevices != null && !pairedDevices.isEmpty()) {
+ discoveredDevices.addAll(pairedDevices);
+ }
+
+ // 开始扫描
+ new Handler().postDelayed(() -> {
+ stopBleScan();
+ showDeviceListDialog();
+ }, 10000); // 10秒后自动停止扫描
+ }
+
+ /**
+ * 停止扫描
+ */
+ private void stopBleScan() {
+ hideDialogLoading();
+ }
+
+ /**
+ * 显示设备列表对话框
+ */
+ private void showDeviceListDialog() {
+ if (discoveredDevices.isEmpty()) {
+ ToastUtil.showShort(mContext, "未发现蓝牙设备");
+ return;
+ }
+
+ String[] deviceNames = new String[discoveredDevices.size()];
+ for (int i = 0; i < discoveredDevices.size(); i++) {
+ BluetoothDevice device = discoveredDevices.get(i);
+ String name = device.getName();
+ if (name == null || name.isEmpty()) {
+ name = "未知设备";
+ }
+ deviceNames[i] = name + "\n" + device.getAddress();
+ }
+
+ AlertDialog.Builder builder = new AlertDialog.Builder(this);
+ builder.setTitle("发现 " + discoveredDevices.size() + " 个设备");
+ builder.setItems(deviceNames, (dialog, which) -> {
+ BluetoothDevice selectedDevice = discoveredDevices.get(which);
+ connectToDevice(selectedDevice);
+ });
+ builder.setNegativeButton("取消", null);
+ deviceListDialog = builder.show();
+ }
+
+ /**
+ * 连接蓝牙设备
+ */
+ private void connectToDevice(BluetoothDevice device) {
+ showLoadingDialog();
+ String deviceName = device.getName();
+ if (deviceName == null || deviceName.isEmpty()) {
+ deviceName = "未知设备";
+ }
+ ToastUtil.showShort(mContext, "正在连接: " + deviceName);
+
+ // TODO: 这里可以调用 DeviceBleManager 进行连接
+ // DeviceBleManager bleManager = new DeviceBleManager(this);
+ // bleManager.connect(device);
+
+ // 模拟连接成功
+ String finalDeviceName = deviceName;
+ new Handler().postDelayed(() -> {
+ hideDialogLoading();
+ ToastUtil.showShort(mContext, "连接成功: " + finalDeviceName);
+ // 获取设备信息
+ getDeviceInfo(device);
+ }, 2000);
+ }
+
+ /**
+ * 获取蓝牙设备信息
+ */
+ private void getDeviceInfo(BluetoothDevice device) {
+ String deviceName = device.getName();
+ String deviceAddress = device.getAddress();
+
+ if (deviceName == null || deviceName.isEmpty()) {
+ deviceName = "未知设备";
+ }
+
+ ToastUtil.showShort(mContext, "设备名称: " + deviceName + "\n设备地址: " + deviceAddress);
+
+ // TODO: 将设备信息传递给后续业务逻辑
+ // 例如跳转到下一个页面或保存设备信息
+ }
+
+
+ private void initListener() {
+ setClick(viewBinding.includedTitle.imgBack);
+ setClick(viewBinding.tvScanAdd);
+ setClick(viewBinding.btnBleScan);
+ setClick(viewBinding.imgDeviceItem);
+ }
+
+ 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.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;
+ if(!hasRecordPermission(readPermission)){
+ getPermissionRequst(readPermission,"权限申请",
+ "智能浇水需要您的授权访问相机,并使用扫一扫",REQUEST_EVENT_CODE_10001);
+ }else{
+ scanQrcode();
+ }
+ break;
+
+ case R.id.btn_ble_scan:
+ // 扫描蓝牙设备
+ startBleScan();
+ 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, "蓝牙已开启");
+ } else {
+ ToastUtil.showShort(mContext, "请开启蓝牙以扫描设备");
+ }
+ }
+ }
+
+ @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();
+ startBleScan();
+ } 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 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 perms) {
+ hidePermissionDialog();
+ if (requestCode == REQUEST_EVENT_CODE_10001) {
+ scanQrcode();
+ }
+ }
+
+ @Override
+ public void onPermissionsDenied(int requestCode, @NonNull List 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();
+ BluetoothLeScannerCompat scanner = BluetoothLeScannerCompat.getScanner();
+ scanner.stopScan(new ScanCallback() {
+ @Override
+ public void onScanResult(int callbackType, @NonNull ScanResult result) {
+ super.onScanResult(callbackType, result);
+ }
+
+ @Override
+ public void onBatchScanResults(@NonNull List results) {
+ super.onBatchScanResults(results);
+ }
+
+ @Override
+ public void onScanFailed(int errorCode) {
+ super.onScanFailed(errorCode);
+ }
+ });
+ }
+}
diff --git a/app/src/main/java/com/ckkj/water/device/DeviceControlActivity.java b/app/src/main/java/com/ckkj/water/device/DeviceControlActivity.java
index 9c5a0da..38121ca 100644
--- a/app/src/main/java/com/ckkj/water/device/DeviceControlActivity.java
+++ b/app/src/main/java/com/ckkj/water/device/DeviceControlActivity.java
@@ -2,6 +2,7 @@ package com.ckkj.water.device;
import android.content.Intent;
import android.os.Bundle;
+import android.text.TextUtils;
import android.view.View;
import androidx.annotation.Nullable;
@@ -10,6 +11,7 @@ import com.chad.library.adapter.base.BaseQuickAdapter;
import com.ckkj.water.EventMessage;
import com.ckkj.water.R;
import com.ckkj.water.base.BaseActivity;
+import com.ckkj.water.base.BaseFragment;
import com.ckkj.water.custom.GridSpacingItemDecoration;
import com.ckkj.water.custom.view.CustomBubbleAttachPopup;
import com.ckkj.water.databinding.DeviceControlLayoutBinding;
@@ -19,6 +21,7 @@ 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.show.ToastUtil;
import com.gyf.immersionbar.ImmersionBar;
import com.lxj.xpopup.XPopup;
@@ -38,6 +41,8 @@ public class DeviceControlActivity extends BaseActivity mTimeList = new ArrayList<>();
private WaterDeviceEntity mDeviceEntity;
private DeviceTimeSelectAdapter mAdapter;
+ //用户自定义的浇水时长
+ private int mCustomDuration = 0;
@Override
public DevicePresenter createPresenter() {
return new DevicePresenter(new DeviceImpl());
@@ -81,8 +86,15 @@ public class DeviceControlActivity extends BaseActivity 1
+ * 10min -> 10
+ * 1h -> 60
+ * 2h -> 120
+ *
+ * @param timeValue 时间字符串
+ * @return 分钟数
+ */
+ public static int convertToMinutes(String timeValue) {
+ if (TextUtils.isEmpty(timeValue)) {
+ return 0;
+ }
+
+ try {
+ if (timeValue.endsWith("min")) {
+ return Integer.parseInt(
+ timeValue.substring(0, timeValue.length() - 3)
+ );
+ }
+
+ if (timeValue.endsWith("h")) {
+ return Integer.parseInt(
+ timeValue.substring(0, timeValue.length() - 1)
+ ) * 60;
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return 0;
+ }
+
+
+
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
diff --git a/app/src/main/java/com/ckkj/water/device/DeviceSettingsActivity.java b/app/src/main/java/com/ckkj/water/device/DeviceSettingsActivity.java
index 9e6aaab..5006137 100644
--- a/app/src/main/java/com/ckkj/water/device/DeviceSettingsActivity.java
+++ b/app/src/main/java/com/ckkj/water/device/DeviceSettingsActivity.java
@@ -81,7 +81,9 @@ public class DeviceSettingsActivity extends BaseActivity mDatas = new ArrayList<>();
private int mSelPostion = -1;
- public DeviceTimeSelectAdapter(Context context,int layoutResId, @Nullable List data) {
+
+ public int getmSelPostion() {
+ return mSelPostion;
+ }
+
+ public void setmSelPostion(int mSelPostion) {
+ this.mSelPostion = mSelPostion;
+ }
+
+ public DeviceTimeSelectAdapter(Context context, int layoutResId, @Nullable List data) {
super(layoutResId, data);
this.mContext = context;
this.mDatas = data;
diff --git a/app/src/main/java/com/ckkj/water/device/mvp/DeviceImpl.java b/app/src/main/java/com/ckkj/water/device/mvp/DeviceImpl.java
index ec3465e..b59032b 100644
--- a/app/src/main/java/com/ckkj/water/device/mvp/DeviceImpl.java
+++ b/app/src/main/java/com/ckkj/water/device/mvp/DeviceImpl.java
@@ -166,8 +166,43 @@ public class DeviceImpl implements DeviceContract.DataModel{
}
}
+ /**
+ * 手动开启关闭设备
+ * @param json
+ * @param callBack
+ */
@Override
public void turnOnOffDevice(JSONObject json, IndexContract.CallBack callBack) {
+ try {
+ NetWorkManager.getRequest().switchDevice(NetWorkManager.getToken(), NetWorkManager.toRequestBody(json))
+ .subscribeOn(Schedulers.io())
+ .unsubscribeOn(Schedulers.io())
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe(new Observer() {
+ @Override
+ public void onSubscribe(@NonNull Disposable d) {
+ }
+ @Override
+ public void onNext(@NonNull BaseBean bean) {
+ if (bean.getCode() == 200) {
+ callBack.success(bean,0);
+ } else {
+ callBack.fail(bean.getMessage());
+ }
+ }
+
+ @Override
+ public void onError(@NonNull Throwable e) {
+ callBack.fail(e.getMessage());
+ }
+
+ @Override
+ public void onComplete() {
+ }
+ });
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
}
}
diff --git a/app/src/main/java/com/ckkj/water/device/mvp/DevicePresenter.java b/app/src/main/java/com/ckkj/water/device/mvp/DevicePresenter.java
index d271344..2d3e375 100644
--- a/app/src/main/java/com/ckkj/water/device/mvp/DevicePresenter.java
+++ b/app/src/main/java/com/ckkj/water/device/mvp/DevicePresenter.java
@@ -129,4 +129,37 @@ public class DevicePresenter extends BasePresenter {
}
});
}
+
+ /**
+ * 开启/关闭浇水
+ * @param id
+ * @param status
+ * @param duration
+ */
+ public void switchDeviceWork(String id, String status, int duration) {
+ try {
+ JSONObject json = new JSONObject();
+ json.put("id",id);
+ json.put("workStatus",status);
+// json.put("startTime","09:50");
+ json.put("durationMin",duration + "");
+ impl.turnOnOffDevice(json, new IndexContract.CallBack() {
+ @Override
+ public void success(BaseBean bean,int total) {
+ if(DevicePresenter.this.getView() != null){
+ DevicePresenter.this.getView().turnOnOffDeviceSuccess(bean);
+ }
+ }
+
+ @Override
+ public void fail(String msg) {
+ if(DevicePresenter.this.getView() != null){
+ DevicePresenter.this.getView().showError( msg);
+ }
+ }
+ });
+ } catch (JSONException e) {
+ throw new RuntimeException(e);
+ }
+ }
}
diff --git a/app/src/main/java/com/ckkj/water/history/HistoryFragment.java b/app/src/main/java/com/ckkj/water/history/HistoryFragment.java
index 11ca06e..b1d2fae 100644
--- a/app/src/main/java/com/ckkj/water/history/HistoryFragment.java
+++ b/app/src/main/java/com/ckkj/water/history/HistoryFragment.java
@@ -10,6 +10,7 @@ import androidx.fragment.app.Fragment;
import com.ckkj.water.R;
import com.ckkj.water.base.BaseFragment;
import com.ckkj.water.databinding.HistoryFragmentLayoutBinding;
+import com.ckkj.water.history.entity.WateringRecord;
import com.ckkj.water.history.mvp.HistoryContract;
import com.ckkj.water.history.mvp.HistoryPresenter;
import com.ckkj.water.network.BaseBean;
@@ -97,4 +98,9 @@ public class HistoryFragment extends BaseFragment msg, int total) {
+
+ }
}
diff --git a/app/src/main/java/com/ckkj/water/history/TabHistoryFragment.java b/app/src/main/java/com/ckkj/water/history/TabHistoryFragment.java
index d59bf15..30d7b33 100644
--- a/app/src/main/java/com/ckkj/water/history/TabHistoryFragment.java
+++ b/app/src/main/java/com/ckkj/water/history/TabHistoryFragment.java
@@ -8,6 +8,7 @@ import com.ckkj.water.R;
import com.ckkj.water.base.BaseFragment;
import com.ckkj.water.custom.CustomTimeFilterPopupView;
import com.ckkj.water.custom.CustomTypeFilterPopupView;
+import com.ckkj.water.custom.view.CustomRefreshHeader;
import com.ckkj.water.databinding.TabHistoryFragmentLayoutBinding;
import com.ckkj.water.history.adapter.WateringHistoryAdapter;
import com.ckkj.water.history.entity.WateringRecord;
@@ -22,6 +23,8 @@ import com.google.gson.reflect.TypeToken;
import com.lxj.xpopup.XPopup;
import com.lxj.xpopup.core.BasePopupView;
import com.lxj.xpopup.interfaces.SimpleCallback;
+import com.scwang.smart.refresh.footer.ClassicsFooter;
+import com.scwang.smart.refresh.layout.api.RefreshHeader;
import java.lang.reflect.Type;
import java.util.ArrayList;
@@ -35,17 +38,37 @@ import java.util.List;
public class TabHistoryFragment extends BaseFragment
implements HistoryContract.HistoryView {
- List recordList = new ArrayList<>();
+ private List recordList = new ArrayList<>();
private WateringHistoryAdapter mAdapter;
+ private int mCurrentPage = 1;
+
+ @Override
+ protected void onResumeInitData() {
+ super.onResumeInitData();
+ showLoadingDialog();
+ mPresenter.getWaterHistoryList(mCurrentPage);
+ }
+
@Override
public void initData(Bundle state) {
- String jsonContent = getString(R.string.watering_device_list_json);
- Type type = new TypeToken>() {}.getType();
- recordList = new Gson().fromJson(jsonContent, type);
mAdapter = new WateringHistoryAdapter(mContext,R.layout.tab_history_item_layout,recordList);
viewBinding.rvHisttory.setAdapter(mAdapter);
initListener();
- mPresenter.getWaterHistoryList();
+
+ RefreshHeader header = new CustomRefreshHeader(mContext);
+ viewBinding.refresh.setRefreshHeader(header);
+ viewBinding.refresh.setRefreshFooter(new ClassicsFooter(mContext));
+ viewBinding.refresh.setOnRefreshListener(layout -> {
+ mCurrentPage = 1;
+ viewBinding.refresh.setNoMoreData(false);
+ mPresenter.getWaterHistoryList(mCurrentPage);
+
+ });
+ viewBinding.refresh.setOnLoadMoreListener(layout -> {
+ mCurrentPage++;
+ mPresenter.getWaterHistoryList(mCurrentPage);
+
+ });
}
private void initListener() {
@@ -139,6 +162,46 @@ public class TabHistoryFragment extends BaseFragment list, int total) {
+ hideDialogLoading();
+ List pageList = list == null ? new ArrayList<>() : list;
+ if (mCurrentPage == 1) {
+ viewBinding.refresh.finishRefresh(300);
+ recordList.clear(); // 只在刷新时清除
+ recordList = pageList;
+ } else {
+ viewBinding.refresh.finishLoadMore(300);
+ recordList.addAll(pageList);
+ }
+ mAdapter.setNewData(recordList);
+
+ // 4. 判断是否还有更多数据
+ if (mAdapter.getItemCount() >= total || pageList.size() == 0) {
+ // 使用 post 延迟调用,避免内部状态冲突导致的循环调用
+ viewBinding.refresh.postDelayed(() -> viewBinding.refresh.setNoMoreData(true), 300);
+ viewBinding.relNoMore.setVisibility(View.VISIBLE); // 自定义底部提示"暂无更多数据"
+ } else {
+ viewBinding.refresh.setNoMoreData(false);
+ viewBinding.relNoMore.setVisibility(View.GONE);
+ }
+
+ // 5. 控制空布局和内容显示
+ if (mAdapter.getItemCount() != 0) {
+ viewBinding.refresh.setVisibility(View.VISIBLE);
+ viewBinding.relNoresult.setVisibility(View.GONE);
+ } else {
+ viewBinding.refresh.setVisibility(View.GONE);
+ viewBinding.relNoresult.setVisibility(View.VISIBLE);
+ }
+ }
+
+
@Override
public HistoryPresenter createPresenter() {
return new HistoryPresenter(new HistoryImpl());
@@ -151,11 +214,14 @@ public class TabHistoryFragment extends BaseFragment {
- void success(T msg);
+ void success(T msg, int total);
void fail(String msg);
}
public interface DataModel{
@@ -16,5 +18,7 @@ public class HistoryContract {
}
public interface HistoryView extends IView {
+ //历史记录成功
+ void getHistoryListSuccess(List msg, int total);
}
}
diff --git a/app/src/main/java/com/ckkj/water/history/mvp/HistoryImpl.java b/app/src/main/java/com/ckkj/water/history/mvp/HistoryImpl.java
index 545595a..31e3e1c 100644
--- a/app/src/main/java/com/ckkj/water/history/mvp/HistoryImpl.java
+++ b/app/src/main/java/com/ckkj/water/history/mvp/HistoryImpl.java
@@ -1,9 +1,11 @@
package com.ckkj.water.history.mvp;
import com.ckkj.water.base.entity.MineUserInfoBean;
+import com.ckkj.water.history.entity.WateringRecord;
import com.ckkj.water.network.BaseBean;
import com.ckkj.water.network.NetWorkManager;
+import java.util.List;
import java.util.Map;
import io.reactivex.Observer;
@@ -25,16 +27,16 @@ public class HistoryImpl implements HistoryContract.DataModel{
.subscribeOn(Schedulers.io())
.unsubscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
- .subscribe(new Observer() {
+ .subscribe(new Observer>>() {
@Override
public void onSubscribe(@NonNull Disposable d) {
}
@Override
- public void onNext(@NonNull BaseBean bean) {
+ public void onNext(@NonNull BaseBean> bean) {
if (bean.getCode() == 200) {
- callBack.success(bean.getData());
+ callBack.success(bean.getRows(),bean.getTotal());
}
}
diff --git a/app/src/main/java/com/ckkj/water/history/mvp/HistoryPresenter.java b/app/src/main/java/com/ckkj/water/history/mvp/HistoryPresenter.java
index 6cfb6d3..b6a4e48 100644
--- a/app/src/main/java/com/ckkj/water/history/mvp/HistoryPresenter.java
+++ b/app/src/main/java/com/ckkj/water/history/mvp/HistoryPresenter.java
@@ -1,9 +1,10 @@
package com.ckkj.water.history.mvp;
import com.ckkj.water.base.BasePresenter;
-import com.ckkj.water.network.BaseBean;
+import com.ckkj.water.history.entity.WateringRecord;
import java.util.HashMap;
+import java.util.List;
import java.util.Map;
public class HistoryPresenter extends BasePresenter {
@@ -16,14 +17,14 @@ public class HistoryPresenter extends BasePresenter
/**
* 获取浇水历史
*/
- public void getWaterHistoryList() {
+ public void getWaterHistoryList(int mCurrentPage) {
Map map = new HashMap<>();
- impl.getHistoryList(map, new HistoryContract.CallBack() {
+ impl.getHistoryList(map, new HistoryContract.CallBack>() {
@Override
- public void success(BaseBean bean) {
+ public void success(List list,int total) {
if(HistoryPresenter.this.getView() != null){
-
+ HistoryPresenter.this.getView().getHistoryListSuccess(list,total);
}
}
diff --git a/app/src/main/java/com/ckkj/water/mine/MineInfomationActivity.java b/app/src/main/java/com/ckkj/water/mine/MineInfomationActivity.java
index 53454b6..dcc107c 100644
--- a/app/src/main/java/com/ckkj/water/mine/MineInfomationActivity.java
+++ b/app/src/main/java/com/ckkj/water/mine/MineInfomationActivity.java
@@ -119,7 +119,9 @@ public class MineInfomationActivity extends BaseActivity> getDeviceDetailInfo(@HeaderMap Map headMap, @Path("id") String id);
+
+ //开启/关闭设备
+ @PUT("app/v1/switchDevice")
+ Observable> switchDevice(@HeaderMap Map headMap, @Body RequestBody requestBody);
+
//修改更新设备信息
@PUT("app/v1/updateDeviceInfo")
Observable updateDeviceInfo(@HeaderMap Map headMap, @Body RequestBody requestBody);
@@ -113,7 +119,7 @@ public interface Request {
//查询排程列表
@GET("app/v1/waterLogList")
- Observable waterLogList(@HeaderMap Map headMap,@QueryMap Map map);
+ Observable>> waterLogList(@HeaderMap Map headMap, @QueryMap Map map);
diff --git a/app/src/main/res/layout/add_device_layout.xml b/app/src/main/res/layout/add_device_layout.xml
index ad616b9..29ee08a 100644
--- a/app/src/main/res/layout/add_device_layout.xml
+++ b/app/src/main/res/layout/add_device_layout.xml
@@ -76,4 +76,17 @@
android:layout_marginHorizontal="@dimen/dp_20"
android:layout_marginTop="@dimen/dp_40"
android:gravity="center"/>
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/device_control_layout.xml b/app/src/main/res/layout/device_control_layout.xml
index b950c62..7f5b089 100644
--- a/app/src/main/res/layout/device_control_layout.xml
+++ b/app/src/main/res/layout/device_control_layout.xml
@@ -187,8 +187,8 @@
android:orientation="horizontal"
android:background="@drawable/shape_f9f9f9_corner_5"
android:layout_marginHorizontal="@dimen/dp_20">
-
-
+ android:layout_height="match_parent">
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file