引入蓝牙依赖
This commit is contained in:
@@ -35,6 +35,14 @@
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
|
||||
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
|
||||
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
|
||||
<!-- 蓝牙权限 -->
|
||||
<uses-permission android:name="android.permission.BLUETOOTH" />
|
||||
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
|
||||
<!-- 支持ble的设备 -->
|
||||
<uses-feature
|
||||
android:name="android.hardware.bluetooth_le"
|
||||
android:required="true" />
|
||||
|
||||
<!--后台获取位置信息,若需后台定位则必选-->
|
||||
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
|
||||
<!--用于申请调用A-GPS模块,卫星定位加速-->
|
||||
|
||||
@@ -120,4 +120,7 @@ public class AppConfig {
|
||||
public static String APP_CLIENT_ID = "428a8310cd442757ae699df5d894f051";
|
||||
public static String APP_USER_TYPE = "app_user";
|
||||
|
||||
//蓝牙设备的uuid
|
||||
public static String BLUETOOTH_DEVICE_UUID = "1775244d-6b43-439b-877c-060f2d9bed07";
|
||||
|
||||
}
|
||||
|
||||
@@ -29,7 +29,9 @@ import com.ckkj.water.BuildConfig;
|
||||
import com.ckkj.water.ConstantUtil;
|
||||
import com.ckkj.water.R;
|
||||
import com.ckkj.water.base.BaseActivity;
|
||||
import com.ckkj.water.custom.GridSpacingItemDecoration;
|
||||
import com.ckkj.water.databinding.AddDeviceLayoutBinding;
|
||||
import com.ckkj.water.device.adapter.BleScanDeviceAdapter;
|
||||
import com.ckkj.water.device.mvp.DeviceContract;
|
||||
import com.ckkj.water.device.mvp.DeviceImpl;
|
||||
import com.ckkj.water.device.mvp.DevicePresenter;
|
||||
@@ -72,6 +74,8 @@ public class AddDeviceActivity_copy extends BaseActivity<AddDeviceLayoutBinding,
|
||||
private String mUuid = "1775244d-6b43-439b-877c-060f2d9bed07";
|
||||
private ScanCallback mScanCallback;
|
||||
private boolean bluetoothReady = false;
|
||||
private BleScanDeviceAdapter bleAdapter;
|
||||
private List<WaterDeviceEntity> mDeviceList = new ArrayList<>();
|
||||
|
||||
@Override
|
||||
public DevicePresenter createPresenter() {
|
||||
@@ -90,6 +94,10 @@ public class AddDeviceActivity_copy extends BaseActivity<AddDeviceLayoutBinding,
|
||||
.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();
|
||||
@@ -115,7 +123,6 @@ public class AddDeviceActivity_copy extends BaseActivity<AddDeviceLayoutBinding,
|
||||
if (animationDrawable.isRunning()) {
|
||||
animationDrawable.stop();
|
||||
viewBinding.ivScanAnimation.setVisibility(GONE);
|
||||
viewBinding.imgDeviceItem.setVisibility(VISIBLE);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -141,21 +148,18 @@ public class AddDeviceActivity_copy extends BaseActivity<AddDeviceLayoutBinding,
|
||||
@Override
|
||||
public void onScanResult(int callbackType, @NonNull ScanResult result) {
|
||||
super.onScanResult(callbackType, result);
|
||||
WaterDeviceEntity bean = new WaterDeviceEntity();
|
||||
//设备名字
|
||||
String deviceName = result.getScanRecord() != null ?
|
||||
result.getScanRecord().getDeviceName() : "无名称";
|
||||
//Mac地址
|
||||
String deviceAddress = result.getDevice().getAddress();
|
||||
Log.e("TEST", "扫描到: " + deviceName + " (" + deviceAddress + ")");
|
||||
|
||||
ScanRecord record = result.getScanRecord();
|
||||
bean.setDeviceName(deviceName);
|
||||
bean.setMacAddress(deviceAddress);
|
||||
mDeviceList.add(bean);
|
||||
bleAdapter.notifyItemInserted(mDeviceList.size() - 1);
|
||||
|
||||
if (record != null) {
|
||||
|
||||
List<ParcelUuid> uuids =
|
||||
record.getServiceUuids();
|
||||
Log.e("TEST", "uuids=" + uuids);
|
||||
}
|
||||
|
||||
ToastUtil.showShort(mContext, "扫描到: " + deviceName);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -238,7 +242,6 @@ public class AddDeviceActivity_copy extends BaseActivity<AddDeviceLayoutBinding,
|
||||
setClick(viewBinding.includedTitle.imgBack);
|
||||
setClick(viewBinding.tvScanAdd);
|
||||
setClick(viewBinding.btnBleScan);
|
||||
setClick(viewBinding.imgDeviceItem);
|
||||
}
|
||||
|
||||
private void setClick(View view) {
|
||||
@@ -251,11 +254,11 @@ public class AddDeviceActivity_copy extends BaseActivity<AddDeviceLayoutBinding,
|
||||
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.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:
|
||||
//检测有无相机权限
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
package com.ckkj.water.device.adapter;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.chad.library.adapter.base.BaseQuickAdapter;
|
||||
import com.chad.library.adapter.base.BaseViewHolder;
|
||||
import com.ckkj.water.R;
|
||||
import com.ckkj.water.index.entity.WaterDeviceEntity;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author fengxiaoyang
|
||||
* @date 2026/6/3
|
||||
* @description 扫描到的设备适配器
|
||||
*/
|
||||
public class BleScanDeviceAdapter extends BaseQuickAdapter<WaterDeviceEntity, BaseViewHolder> {
|
||||
private Context mContext;
|
||||
public BleScanDeviceAdapter(Context context,int layoutResId, @Nullable List<WaterDeviceEntity> data) {
|
||||
super(layoutResId, data);
|
||||
mContext = context;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void convert(BaseViewHolder helper, WaterDeviceEntity item) {
|
||||
helper.setText(R.id.tv_device_name,item.getDeviceName());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
package com.ckkj.water.utils.manager;
|
||||
|
||||
import android.bluetooth.BluetoothGatt;
|
||||
import android.bluetooth.BluetoothGattCharacteristic;
|
||||
import android.bluetooth.BluetoothGattService;
|
||||
import android.content.Context;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.UUID;
|
||||
|
||||
import no.nordicsemi.android.ble.BleManager;
|
||||
|
||||
/**
|
||||
* @author fengxiaoyang
|
||||
* @date 2026/6/3
|
||||
* @description 蓝牙设备管理
|
||||
*/
|
||||
public class WaterDeviceManager extends BleManager {
|
||||
private BluetoothGattCharacteristic writeCharacteristic;
|
||||
private BluetoothGattCharacteristic notifyCharacteristic;
|
||||
|
||||
public WaterDeviceManager(@NonNull Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
protected BleManagerGattCallback getGattCallback() {
|
||||
return new DeviceGattCallback();
|
||||
}
|
||||
|
||||
private class DeviceGattCallback extends BleManagerGattCallback {
|
||||
|
||||
@Override
|
||||
protected void initialize() {
|
||||
|
||||
setNotificationCallback(notifyCharacteristic)
|
||||
.with((device, data) -> {
|
||||
|
||||
byte[] bytes = data.getValue();
|
||||
|
||||
Log.e("TEST", "收到数据: "
|
||||
+ Arrays.toString(bytes));
|
||||
});
|
||||
|
||||
enableNotifications(notifyCharacteristic)
|
||||
.enqueue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRequiredServiceSupported(@NonNull BluetoothGatt gatt) {
|
||||
|
||||
BluetoothGattService service =
|
||||
gatt.getService(UUID.fromString(
|
||||
"0000ffff-0000-1000-8000-00805f9b34fb"));
|
||||
|
||||
if (service == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
writeCharacteristic =
|
||||
service.getCharacteristic(UUID.fromString(
|
||||
"0000ff01-0000-1000-8000-00805f9b34fb"));
|
||||
|
||||
notifyCharacteristic =
|
||||
service.getCharacteristic(UUID.fromString(
|
||||
"0000ff02-0000-1000-8000-00805f9b34fb"));
|
||||
|
||||
return writeCharacteristic != null
|
||||
&& notifyCharacteristic != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onServicesInvalidated() {
|
||||
writeCharacteristic = null;
|
||||
notifyCharacteristic = null;
|
||||
}
|
||||
}
|
||||
|
||||
public void send(byte[] data) {
|
||||
|
||||
if (writeCharacteristic == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
writeCharacteristic(writeCharacteristic, data)
|
||||
.enqueue();
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
@@ -43,14 +45,19 @@
|
||||
android:layout_width="@dimen/dp_200"
|
||||
android:layout_height="@dimen/dp_200"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:src="@drawable/anim_add_device_scan"/>
|
||||
android:src="@drawable/anim_add_device_scan"
|
||||
android:visibility="visible"/>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/img_device_item"
|
||||
android:layout_width="@dimen/dp_150"
|
||||
android:layout_height="@dimen/dp_150"
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/rv_devices"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:src="@mipmap/ic_launcher"
|
||||
android:paddingHorizontal="@dimen/dp_5"
|
||||
android:layout_marginTop="@dimen/dp_5"
|
||||
tools:listitem="@layout/scan_ble_device_item"
|
||||
app:spanCount="4"
|
||||
app:layoutManager="androidx.recyclerview.widget.GridLayoutManager"
|
||||
android:visibility="gone"/>
|
||||
|
||||
<TextView
|
||||
|
||||
23
app/src/main/res/layout/scan_ble_device_item.xml
Normal file
23
app/src/main/res/layout/scan_ble_device_item.xml
Normal file
@@ -0,0 +1,23 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/dp_5"
|
||||
android:gravity="center_horizontal">
|
||||
<com.makeramen.roundedimageview.RoundedImageView
|
||||
android:id="@+id/img_device"
|
||||
android:layout_width="@dimen/dp_60"
|
||||
android:layout_height="@dimen/dp_60"
|
||||
android:src="@mipmap/app_logo"
|
||||
app:riv_corner_radius="@dimen/dp_10"/>
|
||||
<TextView
|
||||
android:id="@+id/tv_device_name"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/dp_5"
|
||||
android:text="设备名称"
|
||||
android:textColor="@color/textPrimaryColor"
|
||||
android:textSize="13sp"/>
|
||||
</LinearLayout>
|
||||
Reference in New Issue
Block a user