更新版本

This commit is contained in:
fengjignqi
2026-07-03 11:42:04 +08:00
parent 21d834d805
commit 5a72fd98af
5 changed files with 499 additions and 504 deletions

View File

@@ -168,11 +168,11 @@
android:screenOrientation="portrait" android:screenOrientation="portrait"
android:windowSoftInputMode="adjustResize"/> android:windowSoftInputMode="adjustResize"/>
<activity <activity
android:name="com.ckkj.water.device.AddDeviceActivity" android:name="com.ckkj.water.device.AddDeviceActivity_cpoy2"
android:screenOrientation="portrait" android:screenOrientation="portrait"
android:windowSoftInputMode="adjustResize"/> android:windowSoftInputMode="adjustResize"/>
<activity <activity
android:name="com.ckkj.water.device.AddDeviceActivity_copy" android:name="com.ckkj.water.device.AddDeviceActivity"
android:screenOrientation="portrait" android:screenOrientation="portrait"
android:windowSoftInputMode="adjustResize"/> android:windowSoftInputMode="adjustResize"/>
<activity <activity

View File

@@ -1,21 +1,36 @@
package com.ckkj.water.device; package com.ckkj.water.device;
import static android.view.View.GONE; import static android.view.View.GONE;
import static android.view.View.VISIBLE;
import android.Manifest; 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.Intent;
import android.content.pm.PackageManager;
import android.graphics.drawable.AnimationDrawable; import android.graphics.drawable.AnimationDrawable;
import android.os.Build;
import android.os.Bundle; 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.view.View;
import android.widget.ImageView; import android.widget.ImageView;
import androidx.annotation.NonNull; 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.ConstantUtil;
import com.ckkj.water.R; import com.ckkj.water.R;
import com.ckkj.water.base.BaseActivity; import com.ckkj.water.base.BaseActivity;
import com.ckkj.water.custom.GridSpacingItemDecoration;
import com.ckkj.water.databinding.AddDeviceLayoutBinding; 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.DeviceContract;
import com.ckkj.water.device.mvp.DeviceImpl; import com.ckkj.water.device.mvp.DeviceImpl;
import com.ckkj.water.device.mvp.DevicePresenter; import com.ckkj.water.device.mvp.DevicePresenter;
@@ -23,6 +38,7 @@ import com.ckkj.water.index.entity.WaterDeviceEntity;
import com.ckkj.water.network.BaseBean; import com.ckkj.water.network.BaseBean;
import com.ckkj.water.utils.manager.ActivityManager; import com.ckkj.water.utils.manager.ActivityManager;
import com.ckkj.water.utils.manager.ThemeManager; import com.ckkj.water.utils.manager.ThemeManager;
import com.ckkj.water.utils.manager.WaterDeviceManager;
import com.ckkj.water.utils.show.ToastUtil; import com.ckkj.water.utils.show.ToastUtil;
import com.gyf.immersionbar.ImmersionBar; import com.gyf.immersionbar.ImmersionBar;
import com.maning.mlkitscanner.scan.MNScanManager; import com.maning.mlkitscanner.scan.MNScanManager;
@@ -31,8 +47,17 @@ import com.maning.mlkitscanner.scan.callback.act.MNScanCallback;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Set;
import java.util.UUID;
import no.nordicsemi.android.support.v18.scanner.BluetoothLeScannerCompat;
import no.nordicsemi.android.support.v18.scanner.ScanCallback;
import no.nordicsemi.android.support.v18.scanner.ScanFilter;
import no.nordicsemi.android.support.v18.scanner.ScanRecord;
import no.nordicsemi.android.support.v18.scanner.ScanResult;
import no.nordicsemi.android.support.v18.scanner.ScanSettings;
import pub.devrel.easypermissions.EasyPermissions; import pub.devrel.easypermissions.EasyPermissions;
/** /**
@@ -40,6 +65,21 @@ import pub.devrel.easypermissions.EasyPermissions;
*/ */
public class AddDeviceActivity extends BaseActivity<AddDeviceLayoutBinding, DevicePresenter> public class AddDeviceActivity extends BaseActivity<AddDeviceLayoutBinding, DevicePresenter>
implements DeviceContract.DeviceView, EasyPermissions.PermissionCallbacks { 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 @Override
public DevicePresenter createPresenter() { public DevicePresenter createPresenter() {
return new DevicePresenter(new DeviceImpl()); return new DevicePresenter(new DeviceImpl());
@@ -49,6 +89,7 @@ public class AddDeviceActivity extends BaseActivity<AddDeviceLayoutBinding, Devi
@Override @Override
public void initData(Bundle savedInstanceState) { public void initData(Bundle savedInstanceState) {
super.initData(savedInstanceState); super.initData(savedInstanceState);
ActivityManager.addActivity(this,getClass().getSimpleName() + "_" + ConstantUtil.ADD_DEVICE_FLAG); ActivityManager.addActivity(this,getClass().getSimpleName() + "_" + ConstantUtil.ADD_DEVICE_FLAG);
ImmersionBar.with(this) ImmersionBar.with(this)
.statusBarColor(R.color.mainBackgroundColor) // 设置状态栏颜色 .statusBarColor(R.color.mainBackgroundColor) // 设置状态栏颜色
@@ -56,35 +97,199 @@ public class AddDeviceActivity extends BaseActivity<AddDeviceLayoutBinding, Devi
.titleBar(viewBinding.rlTitle) .titleBar(viewBinding.rlTitle)
.init(); .init();
viewBinding.includedTitle.tvTitle.setText(R.string.add_device_title); 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; ImageView ivScanAnimation = viewBinding.ivScanAnimation;
if (ivScanAnimation.getDrawable() instanceof AnimationDrawable) { if (ivScanAnimation.getDrawable() instanceof AnimationDrawable) {
AnimationDrawable animationDrawable = (AnimationDrawable) ivScanAnimation.getDrawable(); AnimationDrawable animationDrawable = (AnimationDrawable) ivScanAnimation.getDrawable();
animationDrawable.start(); 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 @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)) {
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; ImageView ivScanAnimation = viewBinding.ivScanAnimation;
if (ivScanAnimation.getDrawable() instanceof AnimationDrawable) { if (ivScanAnimation.getDrawable() instanceof AnimationDrawable) {
AnimationDrawable animationDrawable = (AnimationDrawable) ivScanAnimation.getDrawable(); AnimationDrawable animationDrawable = (AnimationDrawable) ivScanAnimation.getDrawable();
if (animationDrawable.isRunning()) { if (animationDrawable.isRunning()) {
animationDrawable.stop(); animationDrawable.stop();
}
viewBinding.ivScanAnimation.setVisibility(GONE); 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) { private void setClick(View view) {
view.setOnClickListener(this::onClick); view.setOnClickListener(this::onClick);
} }
@@ -95,12 +300,6 @@ public class AddDeviceActivity extends BaseActivity<AddDeviceLayoutBinding, Devi
finish(); finish();
break; 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: case R.id.tv_scan_add:
//检测有无相机权限 //检测有无相机权限
String readPermission = Manifest.permission.CAMERA; String readPermission = Manifest.permission.CAMERA;
@@ -111,6 +310,48 @@ public class AddDeviceActivity extends BaseActivity<AddDeviceLayoutBinding, Devi
scanQrcode(); scanQrcode();
} }
break; 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, "需要蓝牙权限才能扫描设备");
}
} }
} }
@@ -167,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 @Override
public void onPermissionsGranted(int requestCode, @NonNull List<String> perms) { public void onPermissionsGranted(int requestCode, @NonNull List<String> perms) {
hidePermissionDialog(); hidePermissionDialog();
if (requestCode == REQUEST_EVENT_CODE_10001) { if (requestCode == REQUEST_EVENT_CODE_10001) {
scanQrcode(); scanQrcode();
}else if(requestCode == REQUEST_EVENT_CODE_10002){
} }
} }
@@ -215,4 +452,17 @@ public class AddDeviceActivity extends BaseActivity<AddDeviceLayoutBinding, Devi
public void queryDeviceBindStatusSuccess(WaterDeviceEntity bean) { public void queryDeviceBindStatusSuccess(WaterDeviceEntity bean) {
} }
@Override
protected void onDestroy() {
super.onDestroy();
// 停止扫描
stopBleScan();
// 断开蓝牙连接
if (waterDeviceManager != null) {
waterDeviceManager.disconnect().enqueue();
waterDeviceManager.close();
waterDeviceManager = null;
}
}
} }

View File

@@ -1,468 +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.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.ParcelUuid;
import android.text.TextUtils;
import android.util.Log;
import android.util.SparseArray;
import android.view.View;
import android.widget.ImageView;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
import androidx.core.content.ContextCompat;
import com.chad.library.adapter.base.BaseQuickAdapter;
import com.ckkj.water.ConstantUtil;
import com.ckkj.water.R;
import com.ckkj.water.base.BaseActivity;
import com.ckkj.water.custom.GridSpacingItemDecoration;
import com.ckkj.water.databinding.AddDeviceLayoutBinding;
import com.ckkj.water.device.adapter.BleScanDeviceAdapter;
import com.ckkj.water.device.mvp.DeviceContract;
import com.ckkj.water.device.mvp.DeviceImpl;
import com.ckkj.water.device.mvp.DevicePresenter;
import com.ckkj.water.index.entity.WaterDeviceEntity;
import com.ckkj.water.network.BaseBean;
import com.ckkj.water.utils.manager.ActivityManager;
import com.ckkj.water.utils.manager.ThemeManager;
import com.ckkj.water.utils.manager.WaterDeviceManager;
import com.ckkj.water.utils.show.ToastUtil;
import com.gyf.immersionbar.ImmersionBar;
import com.maning.mlkitscanner.scan.MNScanManager;
import com.maning.mlkitscanner.scan.callback.act.MNScanCallback;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.UUID;
import no.nordicsemi.android.support.v18.scanner.BluetoothLeScannerCompat;
import no.nordicsemi.android.support.v18.scanner.ScanCallback;
import no.nordicsemi.android.support.v18.scanner.ScanFilter;
import no.nordicsemi.android.support.v18.scanner.ScanRecord;
import no.nordicsemi.android.support.v18.scanner.ScanResult;
import no.nordicsemi.android.support.v18.scanner.ScanSettings;
import pub.devrel.easypermissions.EasyPermissions;
/**
* 添加设备页面
*/
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());
// 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)) {
return;
}
discoveredMacSet.add(deviceAddress);
WaterDeviceEntity bean = new WaterDeviceEntity();
ScanRecord record = result.getScanRecord();
SparseArray<byte[]> manufacturerData = record.getManufacturerSpecificData();
//设备名字
String deviceName = result.getScanRecord() != null ?
result.getScanRecord().getDeviceName() : "无名称";
bean.setDeviceName(deviceName);
bean.setMacAddress(deviceAddress);
mDeviceList.add(bean);
bleAdapter.notifyItemInserted(mDeviceList.size() - 1);
if(bleAdapter.getItemCount() != 0){
viewBinding.rvDevices.setVisibility(VISIBLE);
// 停止帧动画
ImageView ivScanAnimation = viewBinding.ivScanAnimation;
if (ivScanAnimation.getDrawable() instanceof AnimationDrawable) {
AnimationDrawable animationDrawable = (AnimationDrawable) ivScanAnimation.getDrawable();
if (animationDrawable.isRunning()) {
animationDrawable.stop();
}
viewBinding.ivScanAnimation.setVisibility(GONE);
}
}
}
@Override
public void onBatchScanResults(@NonNull List<ScanResult> results) {
super.onBatchScanResults(results);
Log.e("TEST", "批量结果: " + results.size() + " 个设备");
}
@Override
public void onScanFailed(int errorCode) {
super.onScanFailed(errorCode);
Log.e("TEST", "扫描失败: " + errorCode);
ToastUtil.showShort(mContext, "扫描失败,错误码: " + errorCode);
}
};
scanner.startScan(filters, settings, mScanCallback);
}
/**
* 停止 BLE 扫描
*/
private void stopBleScan() {
if (mScanCallback != null) {
BluetoothLeScannerCompat scanner = BluetoothLeScannerCompat.getScanner();
scanner.stopScan(mScanCallback);
Log.e("TEST", "停止扫描");
}
}
/**
* 初始化蓝牙适配器
*/
private void initBluetooth() {
BluetoothManager bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
if (bluetoothManager != null) {
bluetoothAdapter = bluetoothManager.getAdapter();
}
if (bluetoothAdapter == null) {
ToastUtil.showShort(mContext, "设备不支持蓝牙");
return;
}
try {
// 检查蓝牙是否开启
if (!bluetoothAdapter.isEnabled()) {
Log.e("TEST", "initBluetooth: 蓝牙未开启,请求开启");
Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
} else {
bluetoothReady = true;
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* 检查蓝牙权限
*/
private boolean checkBluetoothPermissions() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
String[] readPermission = new String[]{
Manifest.permission.BLUETOOTH_SCAN,
Manifest.permission.BLUETOOTH_CONNECT,
Manifest.permission.ACCESS_FINE_LOCATION
};
if (!hasRecordPermission(readPermission)) {
// 没有权限只在ACTION_DOWN时去申请
getMorePermissionRequst(readPermission,"蓝牙扫描权限申请",
"智能浇水需要您的授权,获取蓝牙权限添加设备",REQUEST_EVENT_CODE_10003);
return false;
}
} else {
// Android 12 以下需要位置权限才能扫描蓝牙
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
!= PackageManager.PERMISSION_GRANTED) {
requestPermissions(new String[]{
Manifest.permission.ACCESS_FINE_LOCATION
}, REQUEST_BLUETOOTH_PERMISSION);
return false;
}
}
return true;
}
private void setClick(View view) {
view.setOnClickListener(this::onClick);
}
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(WaterDeviceEntity 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, String status) {
}
@Override
public void queryDeviceBindStatusSuccess(WaterDeviceEntity bean) {
}
@Override
protected void onDestroy() {
super.onDestroy();
// 停止扫描
stopBleScan();
// 断开蓝牙连接
if (waterDeviceManager != null) {
waterDeviceManager.disconnect().enqueue();
waterDeviceManager.close();
waterDeviceManager = null;
}
}
}

View File

@@ -0,0 +1,218 @@
package com.ckkj.water.device;
import static android.view.View.GONE;
import android.Manifest;
import android.content.Intent;
import android.graphics.drawable.AnimationDrawable;
import android.os.Bundle;
import android.os.Handler;
import android.view.View;
import android.widget.ImageView;
import androidx.annotation.NonNull;
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 pub.devrel.easypermissions.EasyPermissions;
/**
* 添加设备页面
*/
public class AddDeviceActivity_cpoy2 extends BaseActivity<AddDeviceLayoutBinding, DevicePresenter>
implements DeviceContract.DeviceView, EasyPermissions.PermissionCallbacks {
@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);
// 启动帧动画
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);
}
}
}
},3000);
initListener();
}
private void initListener() {
setClick(viewBinding.includedTitle.imgBack);
setClick(viewBinding.tvScanAdd);
}
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;
}
}
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 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();
}
}
@Override
public void onPermissionsDenied(int requestCode, @NonNull List<String> perms) {
}
@Override
public void addDeviceSuccess(WaterDeviceEntity 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, String status) {
}
@Override
public void queryDeviceBindStatusSuccess(WaterDeviceEntity bean) {
}
}

View File

@@ -8,7 +8,6 @@ import android.content.Intent;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.os.Build; import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler;
import android.text.TextUtils; import android.text.TextUtils;
import android.view.View; import android.view.View;
@@ -23,11 +22,9 @@ import com.ckkj.water.custom.view.CustomRefreshHeader;
import com.ckkj.water.databinding.IndexFragmentLayoutBinding; import com.ckkj.water.databinding.IndexFragmentLayoutBinding;
import com.ckkj.water.ConstantUtil; import com.ckkj.water.ConstantUtil;
import com.ckkj.water.device.AddDeviceActivity; import com.ckkj.water.device.AddDeviceActivity;
import com.ckkj.water.device.AddDeviceActivity_copy;
import com.ckkj.water.device.DeviceControlActivity; import com.ckkj.water.device.DeviceControlActivity;
import com.ckkj.water.device.DeviceReNameActivity; import com.ckkj.water.device.DeviceReNameActivity;
import com.ckkj.water.device.SelectWifiActivity; import com.ckkj.water.device.SelectWifiActivity;
import com.ckkj.water.history.entity.WateringRecord;
import com.ckkj.water.index.adapter.DeviceAdapter; import com.ckkj.water.index.adapter.DeviceAdapter;
import com.ckkj.water.index.entity.WaterDeviceEntity; import com.ckkj.water.index.entity.WaterDeviceEntity;
import com.ckkj.water.index.mvp.IndexContract; import com.ckkj.water.index.mvp.IndexContract;
@@ -35,9 +32,7 @@ import com.ckkj.water.index.mvp.IndexImpl;
import com.ckkj.water.index.mvp.IndexPresenter; import com.ckkj.water.index.mvp.IndexPresenter;
import com.ckkj.water.network.BaseBean; import com.ckkj.water.network.BaseBean;
import com.ckkj.water.permission.PermissionActivity; import com.ckkj.water.permission.PermissionActivity;
import com.ckkj.water.plan.entity.WaterPlanWeekEntity;
import com.ckkj.water.utils.show.ToastUtil; import com.ckkj.water.utils.show.ToastUtil;
import com.google.gson.Gson;
import com.maning.mlkitscanner.scan.MNScanManager; import com.maning.mlkitscanner.scan.MNScanManager;
import com.maning.mlkitscanner.scan.callback.act.MNScanCallback; import com.maning.mlkitscanner.scan.callback.act.MNScanCallback;
import com.scwang.smart.refresh.footer.ClassicsFooter; import com.scwang.smart.refresh.footer.ClassicsFooter;
@@ -141,7 +136,7 @@ public class IndexFragment extends BaseFragment<IndexFragmentLayoutBinding, Inde
case R.id.img_add: case R.id.img_add:
if(checkBluetoothPermissions()){ if(checkBluetoothPermissions()){
goTo(mContext, AddDeviceActivity_copy.class,null); goTo(mContext, AddDeviceActivity.class,null);
}else{ }else{
goTo(mContext, PermissionActivity.class,null); goTo(mContext, PermissionActivity.class,null);