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