From 49dc0c35a2c13f4ceeba484b16d250fa970e39b1 Mon Sep 17 00:00:00 2001 From: wenfei Date: Fri, 26 Sep 2025 18:23:16 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=20=E8=93=9D=E7=89=99?= =?UTF-8?q?=E6=89=AB=E6=8F=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/AndroidManifest.xml | 30 +- .../dywoa/bleUtil/BlueTestInfoActivity.java | 410 ++++++++++++++++++ .../bleUtil/BlueToothDeviceActivity.java | 196 +++++++++ .../dywoa/bleUtil/BluetoothLeService.java | 351 +++++++++++++++ .../dywoa/bleUtil/LeDeviceListAdapter.java | 110 +++++ .../dywoa/ui/fragment/HomeFragment.java | 36 +- .../res/layout/activity_blue_tooth_device.xml | 55 +++ .../res/layout/activity_bluetoothlist.xml | 53 +++ app/src/main/res/layout/listitem_device.xml | 41 ++ 9 files changed, 1259 insertions(+), 23 deletions(-) create mode 100755 app/src/main/java/com/rehome/dywoa/bleUtil/BlueTestInfoActivity.java create mode 100644 app/src/main/java/com/rehome/dywoa/bleUtil/BlueToothDeviceActivity.java create mode 100755 app/src/main/java/com/rehome/dywoa/bleUtil/BluetoothLeService.java create mode 100644 app/src/main/java/com/rehome/dywoa/bleUtil/LeDeviceListAdapter.java create mode 100644 app/src/main/res/layout/activity_blue_tooth_device.xml create mode 100644 app/src/main/res/layout/activity_bluetoothlist.xml create mode 100644 app/src/main/res/layout/listitem_device.xml diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index cccff4c..cc1c6fe 100755 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -2,6 +2,22 @@ + + + + + + + + + + + @@ -78,8 +94,6 @@ tools:replace="android:allowBackup" tools:targetApi="s"> - - + + + mPermissionList = new ArrayList(); + + @Override + public int getContentViewID() { + return R.layout.activity_bluetoothlist; + } + + @Override + public void initView() { + initToolbar("蓝牙数据管理", "扫描并确认", new View.OnClickListener() { + @Override + public void onClick(View v) { + showLog("蓝牙数据管理"); + mLeDeviceListAdapter.clear(); + mLeDeviceListAdapter.notifyDataSetChanged(); + scanLeDevice(true); + } + }); + lv = findViewById(R.id.lv); + txData = findViewById(R.id.tx_data); + ztData = findViewById(R.id.zt_data); + } + + @Override + public void initData() { + initPermission(); + mHandler = new Handler(); + if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) { + Toast.makeText(this, R.string.ble_not_supported, Toast.LENGTH_SHORT).show(); + finish(); + } + final BluetoothManager bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE); + mBluetoothAdapter = bluetoothManager.getAdapter(); + + if (mBluetoothAdapter == null) { + Toast.makeText(this, R.string.error_bluetooth_not_supported, Toast.LENGTH_SHORT).show(); + finish(); + return; + } + setAdapter(); + LocalBroadcastManager.getInstance(BlueTestInfoActivity.this).registerReceiver(mGattUpdateReceiver, makeGattUpdateIntentFilter()); + Intent gattServiceIntent = new Intent(BlueTestInfoActivity.this, BluetoothLeService.class); + bindService(gattServiceIntent, mServiceConnection, BIND_AUTO_CREATE); + initconn = true; + } + + // todo 蓝牙动态申请权限 + private void initPermission(){ + if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.S){ + // Android 版本大于等于 Android12 时 + // 只包括蓝牙这部分的权限,其余的需要什么权限自己添加 + mPermissionList.add(Manifest.permission.BLUETOOTH_SCAN); + mPermissionList.add(Manifest.permission.BLUETOOTH_ADVERTISE); + mPermissionList.add(Manifest.permission.BLUETOOTH_CONNECT); + } else { + // Android 版本小于 Android12 及以下版本 + mPermissionList.add(Manifest.permission.ACCESS_COARSE_LOCATION); + mPermissionList.add(Manifest.permission.ACCESS_FINE_LOCATION); + } + Log.i("app",new Gson().toJson(mPermissionList.toArray(new String[0]))); + ActivityCompat.requestPermissions(this,mPermissionList.toArray(new String[0]),1001); + } + + @Override + public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults); + Log.i("app","onRequestPermissionsResult"); + Log.i("app",String.valueOf(grantResults.length)); + Log.i("app",new Gson().toJson(grantResults)); + boolean hasGrant = true; + for (int grantResult : grantResults) { + if (grantResult != 0) { + //未授权 + hasGrant = false; + break; + } + } + if(hasGrant){ + //已授权 + scanLeDevice(true); + }else{ + showToast("您未授权开启蓝牙连接到Blue设备,请先开启权限"); + } + } + + @Override + protected void onResume() { + super.onResume(); + if (!mBluetoothAdapter.isEnabled()) { + if (!mBluetoothAdapter.isEnabled()) { + Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE); + if (ActivityCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH_CONNECT) != PackageManager.PERMISSION_GRANTED) { + // TODO: Consider calling + // ActivityCompat#requestPermissions + // here to request the missing permissions, and then overriding + // public void onRequestPermissionsResult(int requestCode, String[] permissions, + // int[] grantResults) + // to handle the case where the user grants the permission. See the documentation + // for ActivityCompat#requestPermissions for more details. + return; + } + startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT); + } + } + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + if (requestCode == REQUEST_ENABLE_BT && resultCode == Activity.RESULT_CANCELED) { + finish(); + return; + } + super.onActivityResult(requestCode, resultCode, data); + } + + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_BACK) { + finish(); + return true; + } + return super.onKeyDown(keyCode, event); + } + + private void scanLeDevice(final boolean enable) { + if (enable) { + mHandler.postDelayed(() -> { + mScanning = false; + if (ActivityCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH_SCAN) != PackageManager.PERMISSION_GRANTED) { + // TODO: Consider calling + // ActivityCompat#requestPermissions + // here to request the missing permissions, and then overriding + // public void onRequestPermissionsResult(int requestCode, String[] permissions, + // int[] grantResults) + // to handle the case where the user grants the permission. See the documentation + // for ActivityCompat#requestPermissions for more details. + return; + } + mBluetoothAdapter.stopLeScan(mLeScanCallback); + }, SCAN_PERIOD); + + mScanning = true; + mBluetoothAdapter.startLeScan(mLeScanCallback); + } else { + mScanning = false; + mBluetoothAdapter.stopLeScan(mLeScanCallback); + } + } + + //扫描到每台设备后调用回调函数callback. + private BluetoothAdapter.LeScanCallback mLeScanCallback = new BluetoothAdapter.LeScanCallback() { + @Override + public void onLeScan(final BluetoothDevice device, int rssi, byte[] scanRecord) { + runOnUiThread(() -> { + mLeDeviceListAdapter.addDevice(device); + mLeDeviceListAdapter.notifyDataSetChanged(); + }); + } + }; + + private void setAdapter() { + mLeDeviceListAdapter = new LeDeviceListAdapter(); + lv.setAdapter(mLeDeviceListAdapter); + lv.setOnItemClickListener((parent, view, position, id) -> { + final BluetoothDevice device = mLeDeviceListAdapter.getDevice(position); + if (device == null) return; + if (mScanning) { + if (ActivityCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH_SCAN) != PackageManager.PERMISSION_GRANTED) { + // TODO: Consider calling + // ActivityCompat#requestPermissions + // here to request the missing permissions, and then overriding + // public void onRequestPermissionsResult(int requestCode, String[] permissions, + // int[] grantResults) + // to handle the case where the user grants the permission. See the documentation + // for ActivityCompat#requestPermissions for more details. + return; + } + mBluetoothAdapter.stopLeScan(mLeScanCallback); + mScanning = false; + } + + mDeviceAddress = device.getAddress(); + mLeDeviceListAdapter.setSelectItem(position);//记载当前点击选中的节点position,为了变色 + mLeDeviceListAdapter.notifyDataSetChanged(); + + if (initconn) { + if (!mConnected) mBluetoothLeService.connect(mDeviceAddress); + } else { + //registerReceiver(mGattUpdateReceiver, makeGattUpdateIntentFilter()); + LocalBroadcastManager.getInstance(BlueTestInfoActivity.this).registerReceiver(mGattUpdateReceiver, makeGattUpdateIntentFilter()); + Intent gattServiceIntent = new Intent(BlueTestInfoActivity.this, BluetoothLeService.class); + bindService(gattServiceIntent, mServiceConnection, BIND_AUTO_CREATE); + initconn = true; + } + }); + } + + private class LeDeviceListAdapter extends BaseAdapter { + private class ViewHolder { + TextView deviceName; + } + + private ArrayList mLeDevices; + private LayoutInflater mInflator; + + public LeDeviceListAdapter() { + super(); + mLeDevices = new ArrayList(); + mInflator = BlueTestInfoActivity.this.getLayoutInflater(); + } + + public void addDevice(BluetoothDevice device) { + if (!mLeDevices.contains(device)) { + mLeDevices.add(device); + } + } + + public BluetoothDevice getDevice(int position) { + return mLeDevices.get(position); + } + + public void clear() { + mLeDevices.clear(); + } + + @Override + public int getCount() { + return mLeDevices.size(); + } + + @Override + public Object getItem(int i) { + return mLeDevices.get(i); + } + + @Override + public long getItemId(int i) { + return i; + } + + @Override + public View getView(int i, View view, ViewGroup viewGroup) { + ViewHolder viewHolder; + if (view == null) { + view = mInflator.inflate(R.layout.listitem_device, null); + viewHolder = new ViewHolder(); + viewHolder.deviceName = view.findViewById(R.id.device_name); + view.setTag(viewHolder); + } else { + viewHolder = (ViewHolder) view.getTag(); + } + + BluetoothDevice device = mLeDevices.get(i); + if (ActivityCompat.checkSelfPermission(context, Manifest.permission.BLUETOOTH_CONNECT) != PackageManager.PERMISSION_GRANTED) { + // TODO: Consider calling + // ActivityCompat#requestPermissions + // here to request the missing permissions, and then overriding + // public void onRequestPermissionsResult(int requestCode, String[] permissions, + // int[] grantResults) + // to handle the case where the user grants the permission. See the documentation + // for ActivityCompat#requestPermissions for more details. + return null; + } + final String deviceName = device.getName(); + if (deviceName != null && deviceName.length() > 0) + viewHolder.deviceName.setText(deviceName); + else + viewHolder.deviceName.setText(R.string.unknown_device); + //当前点击选中的变色 + if (i == selectItem) { + viewHolder.deviceName.getPaint().setFakeBoldText(true); + viewHolder.deviceName.setTextColor(Color.parseColor("#00FF7F"));//连接之后的颜色 + } else { + viewHolder.deviceName.getPaint().setFakeBoldText(false); + viewHolder.deviceName.setTextColor(Color.parseColor("#000000")); + } + return view; + } + + public void setSelectItem(int selectItem) { + this.selectItem = selectItem; + } + + private int selectItem = -1; + } + + + private final ServiceConnection mServiceConnection = new ServiceConnection() { + @Override + public void onServiceConnected(ComponentName componentName, IBinder service) { + mBluetoothLeService = ((BluetoothLeService.LocalBinder) service).getService(); + if (!mBluetoothLeService.initialize()) { + finish(); + } + mBluetoothLeService.connect(mDeviceAddress); + } + + @Override + public void onServiceDisconnected(ComponentName componentName) { + mBluetoothLeService = null; + } + }; + private final BroadcastReceiver mGattUpdateReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + final String action = intent.getAction(); + if (BluetoothLeService.ACTION_GATT_CONNECTED.equals(action)) { + mConnected = true; + ztData.setText("蓝牙状态:已连接"); + } else if (BluetoothLeService.ACTION_GATT_DISCONNECTED.equals(action)) { + mConnected = false; + ztData.setText("蓝牙状态:已断开"); + } else if (BluetoothLeService.ACTION_GATT_SERVICES_DISCOVERED.equals(action)) { + ztData.setText("蓝牙状态:已连接,仪器准备就绪"); + } else if (BluetoothLeService.ACTION_DATA_AVAILABLE.equals(action)) { + String Data = ""; + String BleData = intent.getStringExtra(BluetoothLeService.EXTRA_DATA); + String type = BleData.substring(0, 1); + if (type.equals("T")) { + Data = "温度:" + BleData.substring(2, 6); + } else { + Data = "震动:" + BleData.substring(2, 6); + } + txData.setText(Data); + + } + } + }; + + + static IntentFilter makeGattUpdateIntentFilter() { + final IntentFilter intentFilter = new IntentFilter(); + intentFilter.addAction(BluetoothLeService.ACTION_GATT_CONNECTED); + intentFilter.addAction(BluetoothLeService.ACTION_GATT_DISCONNECTED); + intentFilter.addAction(BluetoothLeService.ACTION_GATT_SERVICES_DISCOVERED); + intentFilter.addAction(BluetoothLeService.ACTION_DATA_AVAILABLE); + return intentFilter; + } + + @Override + protected void onDestroy() { + scanLeDevice(false); + mLeDeviceListAdapter.clear(); + unbindService(mServiceConnection); + // 注销广播接收器 + LocalBroadcastManager.getInstance(this).unregisterReceiver(mGattUpdateReceiver); + super.onDestroy(); + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/rehome/dywoa/bleUtil/BlueToothDeviceActivity.java b/app/src/main/java/com/rehome/dywoa/bleUtil/BlueToothDeviceActivity.java new file mode 100644 index 0000000..3c65938 --- /dev/null +++ b/app/src/main/java/com/rehome/dywoa/bleUtil/BlueToothDeviceActivity.java @@ -0,0 +1,196 @@ +package com.rehome.dywoa.bleUtil; + +import android.Manifest; +import android.bluetooth.BluetoothAdapter; +import android.bluetooth.BluetoothManager; +import android.bluetooth.le.BluetoothLeScanner; +import android.bluetooth.le.ScanCallback; +import android.bluetooth.le.ScanResult; +import android.content.Context; +import android.content.pm.PackageManager; +import android.os.Build; +import android.os.Bundle; +import android.os.Handler; +import android.util.Log; +import android.view.View; +import android.widget.ListView; +import android.widget.Toast; + +import androidx.activity.EdgeToEdge; +import androidx.annotation.NonNull; +import androidx.appcompat.app.AppCompatActivity; +import androidx.core.app.ActivityCompat; +import androidx.core.graphics.Insets; +import androidx.core.view.ViewCompat; +import androidx.core.view.WindowInsetsCompat; + +import com.google.gson.Gson; +import com.rehome.dywoa.R; +import com.rehome.dywoa.base.BaseActivity; + +import java.util.ArrayList; + +/** + * 蓝牙扫描 + * https://developer.android.google.cn/develop/connectivity/bluetooth/ble/find-ble-devices?hl=zh-cn + */ +public class BlueToothDeviceActivity extends BaseActivity { + + ListView lv; + private BluetoothAdapter mBluetoothAdapter; + private ArrayList mPermissionList = new ArrayList(); + private BluetoothLeScanner bluetoothLeScanner; + private boolean scanning=false; + private Handler handler = new Handler(); + + // Stops scanning after 10 seconds. + private static final long SCAN_PERIOD = 10000; + + //private LeDeviceListAdapter leDeviceListAdapter = new LeDeviceListAdapter(); + private LeDeviceListAdapter mLeDeviceListAdapter; + + @Override + public int getContentViewID() { + return R.layout.activity_blue_tooth_device; + } + + @Override + public void initView() { + initToolbar("蓝牙数据管理", "扫描并确认", new View.OnClickListener() { + @Override + public void onClick(View v) { + showLog("蓝牙数据管理"); + mLeDeviceListAdapter.clear(); + mLeDeviceListAdapter.notifyDataSetChanged(); + initBlueTooth(); + } + }); + lv = findViewById(R.id.lv); + mLeDeviceListAdapter = new LeDeviceListAdapter(BlueToothDeviceActivity.this); + lv.setAdapter(mLeDeviceListAdapter); + } + + @Override + public void initData() { + + } + + private void initPermission(){ + if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.S){ + // Android 版本大于等于 Android12 时 + // 只包括蓝牙这部分的权限,其余的需要什么权限自己添加 + mPermissionList.add(Manifest.permission.BLUETOOTH_SCAN); + mPermissionList.add(Manifest.permission.BLUETOOTH_ADVERTISE); + mPermissionList.add(Manifest.permission.BLUETOOTH_CONNECT); + } else { + // Android 版本小于 Android12 及以下版本 + mPermissionList.add(Manifest.permission.ACCESS_COARSE_LOCATION); + mPermissionList.add(Manifest.permission.ACCESS_FINE_LOCATION); + } + showLog(new Gson().toJson(mPermissionList.toArray(new String[0]))); + ActivityCompat.requestPermissions(this,mPermissionList.toArray(new String[0]),1001); + } + + @Override + public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults); + Log.i("app","onRequestPermissionsResult"); + Log.i("app",String.valueOf(grantResults.length)); + Log.i("app",new Gson().toJson(grantResults)); + boolean hasGrant = true; + for (int grantResult : grantResults) { + if (grantResult != 0) { + //未授权 + hasGrant = false; + break; + } + } + if(hasGrant){ + //已授权 + showToast("已授权低功耗蓝牙"); + BluetoothManager bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE); + mBluetoothAdapter = bluetoothManager.getAdapter(); + if (mBluetoothAdapter == null) { + Toast.makeText(this, R.string.error_bluetooth_not_supported, Toast.LENGTH_SHORT).show(); + }else{ + //可以开始扫描啦 + showLog("可以开始扫描啦"); + bluetoothLeScanner = mBluetoothAdapter.getBluetoothLeScanner(); + scanLeDevice(); + } + //scanLeDevice(true); + }else{ + showToast("您未授权开启蓝牙连接到Blue设备,请先开启权限"); + } + } + + + public void initBlueTooth() { + boolean bluetoothAvailable = getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH); + if(bluetoothAvailable){ + showLog("传统蓝牙可用"); + }else{ + showLog("传统蓝牙不可用"); + } + boolean bluetoothLEAvailable = getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE); + + if(bluetoothLEAvailable){ + showLog("低功耗蓝牙可用"); + initPermission(); + }else{ + showLog("低功耗蓝牙不可用"); + showToast("传感器必须使用低功耗蓝牙,当前设备不支持低功耗蓝牙"); + } + } + + private void scanLeDevice() { + if (!scanning) { + // Stops scanning after a predefined scan period. + handler.postDelayed(new Runnable() { + @Override + public void run() { + scanning = false; + if (ActivityCompat.checkSelfPermission(BlueToothDeviceActivity.this, Manifest.permission.BLUETOOTH_SCAN) != PackageManager.PERMISSION_GRANTED) { + // TODO: Consider calling + // ActivityCompat#requestPermissions + // here to request the missing permissions, and then overriding + // public void onRequestPermissionsResult(int requestCode, String[] permissions, + // int[] grantResults) + // to handle the case where the user grants the permission. See the documentation + // for ActivityCompat#requestPermissions for more details. + showToast("蓝牙扫描未授权"); + return; + } + bluetoothLeScanner.stopScan(leScanCallback); + } + }, SCAN_PERIOD); + scanning = true; + if (ActivityCompat.checkSelfPermission(BlueToothDeviceActivity.this, Manifest.permission.BLUETOOTH_SCAN) != PackageManager.PERMISSION_GRANTED) { + // TODO: Consider calling + // ActivityCompat#requestPermissions + // here to request the missing permissions, and then overriding + // public void onRequestPermissionsResult(int requestCode, String[] permissions, + // int[] grantResults) + // to handle the case where the user grants the permission. See the documentation + // for ActivityCompat#requestPermissions for more details. + showToast("您未授权开启蓝牙连接到Blue设备,请先开启权限"); + return; + } + bluetoothLeScanner.startScan(leScanCallback); + } else { + scanning = false; + bluetoothLeScanner.stopScan(leScanCallback); + } + } + + private ScanCallback leScanCallback = new ScanCallback() { + @Override + public void onScanResult(int callbackType, ScanResult result) { + super.onScanResult(callbackType, result); + showToast("发现新设备啦"); + mLeDeviceListAdapter.addDevice(result.getDevice()); + mLeDeviceListAdapter.notifyDataSetChanged(); + } + }; + +} \ No newline at end of file diff --git a/app/src/main/java/com/rehome/dywoa/bleUtil/BluetoothLeService.java b/app/src/main/java/com/rehome/dywoa/bleUtil/BluetoothLeService.java new file mode 100755 index 0000000..440398d --- /dev/null +++ b/app/src/main/java/com/rehome/dywoa/bleUtil/BluetoothLeService.java @@ -0,0 +1,351 @@ +package com.rehome.dywoa.bleUtil; + +import android.Manifest; +import android.app.Service; +import android.bluetooth.BluetoothAdapter; +import android.bluetooth.BluetoothDevice; +import android.bluetooth.BluetoothGatt; +import android.bluetooth.BluetoothGattCallback; +import android.bluetooth.BluetoothGattCharacteristic; +import android.bluetooth.BluetoothGattService; +import android.bluetooth.BluetoothManager; +import android.bluetooth.BluetoothProfile; +import android.content.Context; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.os.Binder; +import android.os.IBinder; +import android.util.Log; + +import androidx.core.app.ActivityCompat; +import androidx.localbroadcastmanager.content.LocalBroadcastManager; + +import java.util.List; +import java.util.UUID; + + +public class BluetoothLeService extends Service { + + private final static String TAG = BluetoothLeService.class.getSimpleName(); + + private BluetoothManager mBluetoothManager; + private BluetoothAdapter mBluetoothAdapter; + private String mBluetoothDeviceAddress; + private BluetoothGatt mBluetoothGatt; + private int mConnectionState = STATE_DISCONNECTED; + + private static final int STATE_DISCONNECTED = 0; + private static final int STATE_CONNECTING = 1; + private static final int STATE_CONNECTED = 2; + + public final static String ACTION_GATT_CONNECTED = + "com.example.bluetooth.le.ACTION_GATT_CONNECTED"; + public final static String ACTION_GATT_DISCONNECTED = + "com.example.bluetooth.le.ACTION_GATT_DISCONNECTED"; + public final static String ACTION_GATT_SERVICES_DISCOVERED = + "com.example.bluetooth.le.ACTION_GATT_SERVICES_DISCOVERED"; + public final static String ACTION_DATA_AVAILABLE = + "com.example.bluetooth.le.ACTION_DATA_AVAILABLE"; + public final static String EXTRA_DATA = + "com.example.bluetooth.le.EXTRA_DATA"; + + + + // Implements callback methods for GATT events that the app cares about. For example, + // connection change and services discovered. + private final BluetoothGattCallback mGattCallback = new BluetoothGattCallback() { + @Override + public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) { + String intentAction; + if (newState == BluetoothProfile.STATE_CONNECTED) { + intentAction = ACTION_GATT_CONNECTED; + mConnectionState = STATE_CONNECTED; + broadcastUpdate(intentAction); + Log.i(TAG, "Connected to GATT server."); + // Attempts to discover services after successful connection. + if (ActivityCompat.checkSelfPermission(BluetoothLeService.this, Manifest.permission.BLUETOOTH_CONNECT) != PackageManager.PERMISSION_GRANTED) { + // TODO: Consider calling + // ActivityCompat#requestPermissions + // here to request the missing permissions, and then overriding + // public void onRequestPermissionsResult(int requestCode, String[] permissions, + // int[] grantResults) + // to handle the case where the user grants the permission. See the documentation + // for ActivityCompat#requestPermissions for more details. + return; + } + Log.i(TAG, "Attempting to start service discovery:" + + mBluetoothGatt.discoverServices()); + + } else if (newState == BluetoothProfile.STATE_DISCONNECTED) { + intentAction = ACTION_GATT_DISCONNECTED; + mConnectionState = STATE_DISCONNECTED; + Log.i(TAG, "Disconnected from GATT server."); + broadcastUpdate(intentAction); + } + } + + @Override + public void onServicesDiscovered(BluetoothGatt gatt, int status) { + if (status == BluetoothGatt.GATT_SUCCESS) { + broadcastUpdate(ACTION_GATT_SERVICES_DISCOVERED); + ////tsp默认选择一个地址 + BluetoothGattCharacteristic characteristic1= + gatt.getService(UUID.fromString("0000ffe0-0000-1000-8000-00805f9b34fb")).getCharacteristic(UUID.fromString("0000ffe4-0000-1000-8000-00805f9b34fb")); + setCharacteristicNotification(characteristic1,true); + } else { + Log.w(TAG, "onServicesDiscovered received: " + status); + } + } + + @Override + public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) { + if (status == BluetoothGatt.GATT_SUCCESS) { + broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic); + } + } + + @Override + public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) { + broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic); + } + @Override + public void onCharacteristicWrite (BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status){ + + } + }; + + private void broadcastUpdate(final String action) { + final Intent intent = new Intent(action); + LocalBroadcastManager.getInstance(BluetoothLeService.this).sendBroadcast(intent); + } + + //收到数据后,触发广播 + private void broadcastUpdate(final String action, final BluetoothGattCharacteristic characteristic) { + final Intent intent = new Intent(action); + // For all other profiles, writes the data formatted in HEX. + final byte[] data = characteristic.getValue(); + if (data != null && data.length > 0) { + final StringBuilder stringBuilder = new StringBuilder(data.length); + for(byte byteChar : data) + stringBuilder.append(String.format("%02X ", byteChar)); + intent.putExtra(EXTRA_DATA, new String(data) + "\n" + stringBuilder.toString()); + } + LocalBroadcastManager.getInstance(BluetoothLeService.this).sendBroadcast(intent); + } + + public class LocalBinder extends Binder { + public BluetoothLeService getService() { + return BluetoothLeService.this; + } + } + + @Override + public IBinder onBind(Intent intent) { + return mBinder; + } + + @Override + public boolean onUnbind(Intent intent) { + // After using a given device, you should make sure that BluetoothGatt.close() is called + // such that resources are cleaned up properly. In this particular example, close() is + // invoked when the UI is disconnected from the Service. +// close(); + return super.onUnbind(intent); + } + + private final IBinder mBinder = new LocalBinder(); + + /** + * Initializes a reference to the local Bluetooth adapter. + * + * @return Return true if the initialization is successful. + */ + public boolean initialize() { + // For API level 18 and above, get a reference to BluetoothAdapter through + // BluetoothManager. + if (mBluetoothManager == null) { + mBluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE); + if (mBluetoothManager == null) { + Log.e(TAG, "Unable to initialize BluetoothManager."); + return false; + } + } + + mBluetoothAdapter = mBluetoothManager.getAdapter(); + if (mBluetoothAdapter == null) { + Log.e(TAG, "Unable to obtain a BluetoothAdapter."); + return false; + } + + return true; + } + + /** + * Connects to the GATT server hosted on the Bluetooth LE device. + * + * @param address The device address of the destination device. + * + * @return Return true if the connection is initiated successfully. The connection result + * is reported asynchronously through the + * {@code BluetoothGattCallback#onConnectionStateChange(android.bluetooth.BluetoothGatt, int, int)} + * callback. + */ + public boolean connect(final String address) {//连接设备 + if (mBluetoothAdapter == null || address == null) { + Log.w(TAG, "BluetoothAdapter not initialized or unspecified address."); + return false; + } + + // Previously connected device. Try to reconnect. + if (mBluetoothDeviceAddress != null && address.equals(mBluetoothDeviceAddress)&& mBluetoothGatt != null) { + Log.d(TAG, "Trying to use an existing mBluetoothGatt for connection."); + if (ActivityCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH_CONNECT) != PackageManager.PERMISSION_GRANTED) { + // TODO: Consider calling + // ActivityCompat#requestPermissions + // here to request the missing permissions, and then overriding + // public void onRequestPermissionsResult(int requestCode, String[] permissions, + // int[] grantResults) + // to handle the case where the user grants the permission. See the documentation + // for ActivityCompat#requestPermissions for more details. + return false; + } + if (mBluetoothGatt.connect()) { + mConnectionState = STATE_CONNECTING; + return true; + } else { + return false; + } + } + + final BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address); + if (device == null) { + Log.w(TAG, "Device not found. Unable to connect."); + return false; + } + // We want to directly connect to the device, so we are setting the autoConnect + // parameter to false. + mBluetoothGatt = device.connectGatt(this, false, mGattCallback); + Log.d(TAG, "Trying to create a new connection."); + mBluetoothDeviceAddress = address; + mConnectionState = STATE_CONNECTING; + return true; + } + + /** + * Disconnects an existing connection or cancel a pending connection. The disconnection result + * is reported asynchronously through the + * {@code BluetoothGattCallback#onConnectionStateChange(android.bluetooth.BluetoothGatt, int, int)} + * callback. + */ + public void disconnect() { + if (mBluetoothAdapter == null || mBluetoothGatt == null) { + Log.w(TAG, "BluetoothAdapter not initialized"); + return; + } + if (ActivityCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH_CONNECT) != PackageManager.PERMISSION_GRANTED) { + // TODO: Consider calling + // ActivityCompat#requestPermissions + // here to request the missing permissions, and then overriding + // public void onRequestPermissionsResult(int requestCode, String[] permissions, + // int[] grantResults) + // to handle the case where the user grants the permission. See the documentation + // for ActivityCompat#requestPermissions for more details. + return; + } + mBluetoothGatt.disconnect(); + } + + /** + * After using a given BLE device, the app must call this method to ensure resources are + * released properly. + */ + public void close() { + if (mBluetoothGatt == null) { + return; + } + if (ActivityCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH_CONNECT) != PackageManager.PERMISSION_GRANTED) { + // TODO: Consider calling + // ActivityCompat#requestPermissions + // here to request the missing permissions, and then overriding + // public void onRequestPermissionsResult(int requestCode, String[] permissions, + // int[] grantResults) + // to handle the case where the user grants the permission. See the documentation + // for ActivityCompat#requestPermissions for more details. + return; + } + mBluetoothGatt.close(); + mBluetoothGatt = null; + } + + /** + * Request a read on a given {@code BluetoothGattCharacteristic}. The read result is reported + * asynchronously through the {@code BluetoothGattCallback#onCharacteristicRead(android.bluetooth.BluetoothGatt, android.bluetooth.BluetoothGattCharacteristic, int)} + * callback. + * + * @param characteristic The characteristic to read from. + */ + public void readCharacteristic(BluetoothGattCharacteristic characteristic) { + if (mBluetoothAdapter == null || mBluetoothGatt == null) { + Log.w(TAG, "BluetoothAdapter not initialized"); + return; + } + if (ActivityCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH_CONNECT) != PackageManager.PERMISSION_GRANTED) { + // TODO: Consider calling + // ActivityCompat#requestPermissions + // here to request the missing permissions, and then overriding + // public void onRequestPermissionsResult(int requestCode, String[] permissions, + // int[] grantResults) + // to handle the case where the user grants the permission. See the documentation + // for ActivityCompat#requestPermissions for more details. + return; + } + mBluetoothGatt.readCharacteristic(characteristic); + } + public void writeCharacteristic(BluetoothGattCharacteristic characteristic) { + if (mBluetoothAdapter == null || mBluetoothGatt == null) { + Log.w(TAG, "BluetoothAdapter not initialized"); + return; + } + if (ActivityCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH_CONNECT) != PackageManager.PERMISSION_GRANTED) { + // TODO: Consider calling + // ActivityCompat#requestPermissions + // here to request the missing permissions, and then overriding + // public void onRequestPermissionsResult(int requestCode, String[] permissions, + // int[] grantResults) + // to handle the case where the user grants the permission. See the documentation + // for ActivityCompat#requestPermissions for more details. + return; + } + mBluetoothGatt.writeCharacteristic(characteristic); + } + /** + * Enables or disables notification on a give characteristic. + * + * @param characteristic Characteristic to act on. + * @param enabled If true, enable notification. False otherwise. + */ + //选择地址 + public void setCharacteristicNotification(BluetoothGattCharacteristic characteristic, boolean enabled) { + if (mBluetoothAdapter == null || mBluetoothGatt == null) { + Log.w(TAG, "BluetoothAdapter not initialized"); + return; + } + if (ActivityCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH_CONNECT) != PackageManager.PERMISSION_GRANTED) { + // TODO: Consider calling + // ActivityCompat#requestPermissions + // here to request the missing permissions, and then overriding + // public void onRequestPermissionsResult(int requestCode, String[] permissions, + // int[] grantResults) + // to handle the case where the user grants the permission. See the documentation + // for ActivityCompat#requestPermissions for more details. + return; + } + mBluetoothGatt.setCharacteristicNotification(characteristic, enabled); + } + + public List getSupportedGattServices() { + if (mBluetoothGatt == null) return null; + return mBluetoothGatt.getServices(); + } +} + diff --git a/app/src/main/java/com/rehome/dywoa/bleUtil/LeDeviceListAdapter.java b/app/src/main/java/com/rehome/dywoa/bleUtil/LeDeviceListAdapter.java new file mode 100644 index 0000000..3bf7b8a --- /dev/null +++ b/app/src/main/java/com/rehome/dywoa/bleUtil/LeDeviceListAdapter.java @@ -0,0 +1,110 @@ +package com.rehome.dywoa.bleUtil; + +import android.Manifest; +import android.app.Activity; +import android.bluetooth.BluetoothDevice; +import android.content.Context; +import android.content.pm.PackageManager; +import android.graphics.Color; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.BaseAdapter; +import android.widget.TextView; + +import androidx.core.app.ActivityCompat; + +import com.rehome.dywoa.R; + +import java.util.ArrayList; + +public class LeDeviceListAdapter extends BaseAdapter { + private Activity context; + private class ViewHolder { + TextView deviceName; + } + + private ArrayList mLeDevices; + private LayoutInflater mInflator; + + public LeDeviceListAdapter(Activity context) { + super(); + this.context=context; + mLeDevices = new ArrayList(); + mInflator = context.getLayoutInflater(); + } + + public void addDevice(BluetoothDevice device) { + if (!mLeDevices.contains(device)) { + mLeDevices.add(device); + } + } + + public BluetoothDevice getDevice(int position) { + return mLeDevices.get(position); + } + + public void clear() { + mLeDevices.clear(); + } + + @Override + public int getCount() { + return mLeDevices.size(); + } + + @Override + public Object getItem(int i) { + return mLeDevices.get(i); + } + + @Override + public long getItemId(int i) { + return i; + } + + @Override + public View getView(int i, View view, ViewGroup viewGroup) { + LeDeviceListAdapter.ViewHolder viewHolder; + if (view == null) { + view = mInflator.inflate(R.layout.listitem_device, null); + viewHolder = new LeDeviceListAdapter.ViewHolder(); + viewHolder.deviceName = view.findViewById(R.id.device_name); + view.setTag(viewHolder); + } else { + viewHolder = (LeDeviceListAdapter.ViewHolder) view.getTag(); + } + + BluetoothDevice device = mLeDevices.get(i); + if (ActivityCompat.checkSelfPermission(context, Manifest.permission.BLUETOOTH_CONNECT) != PackageManager.PERMISSION_GRANTED) { + // TODO: Consider calling + // ActivityCompat#requestPermissions + // here to request the missing permissions, and then overriding + // public void onRequestPermissionsResult(int requestCode, String[] permissions, + // int[] grantResults) + // to handle the case where the user grants the permission. See the documentation + // for ActivityCompat#requestPermissions for more details. + return null; + } + final String deviceName = device.getName(); + if (deviceName != null && deviceName.length() > 0) + viewHolder.deviceName.setText(deviceName); + else + viewHolder.deviceName.setText(R.string.unknown_device); + //当前点击选中的变色 + if (i == selectItem) { + viewHolder.deviceName.getPaint().setFakeBoldText(true); + viewHolder.deviceName.setTextColor(Color.parseColor("#00FF7F"));//连接之后的颜色 + } else { + viewHolder.deviceName.getPaint().setFakeBoldText(false); + viewHolder.deviceName.setTextColor(Color.parseColor("#000000")); + } + return view; + } + + public void setSelectItem(int selectItem) { + this.selectItem = selectItem; + } + + private int selectItem = -1; +} \ No newline at end of file diff --git a/app/src/main/java/com/rehome/dywoa/ui/fragment/HomeFragment.java b/app/src/main/java/com/rehome/dywoa/ui/fragment/HomeFragment.java index 89feb92..a905ca1 100755 --- a/app/src/main/java/com/rehome/dywoa/ui/fragment/HomeFragment.java +++ b/app/src/main/java/com/rehome/dywoa/ui/fragment/HomeFragment.java @@ -10,22 +10,17 @@ import android.os.Environment; import android.os.Handler; import android.os.Looper; import android.text.TextUtils; -import android.util.Base64; import android.view.View; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.TextView; -import android.widget.Toast; import androidx.activity.result.ActivityResult; import androidx.activity.result.ActivityResultCallback; import androidx.activity.result.ActivityResultLauncher; import androidx.activity.result.contract.ActivityResultContracts; import androidx.annotation.NonNull; -import androidx.core.app.ActivityCompat; -import androidx.core.content.ContextCompat; -import com.google.gson.Gson; import com.rehome.dywoa.App; import com.rehome.dywoa.Contans; import com.rehome.dywoa.MainActivity; @@ -33,36 +28,28 @@ import com.rehome.dywoa.R; import com.rehome.dywoa.adapter.GridViewAdapter; import com.rehome.dywoa.base.BaseFragment; import com.rehome.dywoa.bean.FaceRecognitionResult; -import com.rehome.dywoa.bean.FwSingleLoginResult; import com.rehome.dywoa.bean.GridItem; import com.rehome.dywoa.bean.WaitForBean; +import com.rehome.dywoa.bleUtil.BlueTestInfoActivity; +import com.rehome.dywoa.bleUtil.BlueToothDeviceActivity; import com.rehome.dywoa.ui.activity.BiShowActivity; import com.rehome.dywoa.ui.activity.EveryDateRiskControllerListActivity; -import com.rehome.dywoa.ui.activity.FaceRecognitionActivity; import com.rehome.dywoa.ui.activity.FaceRecognitionAppActivity; import com.rehome.dywoa.ui.activity.FanWeiActivity; import com.rehome.dywoa.ui.activity.HightRiskActivity; import com.rehome.dywoa.ui.activity.JiZhuActivity; import com.rehome.dywoa.ui.activity.KksSearchActivity; -import com.rehome.dywoa.ui.activity.RunLogBaseActivity; -import com.rehome.dywoa.ui.activity.RunLogListActivity; import com.rehome.dywoa.ui.activity.SisBaseActivity; -import com.rehome.dywoa.ui.activity.UseCarActivity; -import com.rehome.dywoa.ui.activity.UseSealActivity; import com.rehome.dywoa.ui.activity.WaitForToDoActivity; import com.rehome.dywoa.ui.activity.YhscpActivity; import com.rehome.dywoa.ui.activity.YjyaActivity; import com.rehome.dywoa.ui.activity.sbxdjgl.SbxdjglActivity; import com.rehome.dywoa.ui.activity.sbxj.XscbglActivity; -import com.rehome.dywoa.utils.DataPassUtils; import com.rehome.dywoa.utils.GsonUtils; import com.rehome.dywoa.utils.HttpListener; import com.rehome.dywoa.utils.NoProgresshttpUtils; import com.rehome.dywoa.utils.NohttpUtils; -import com.rehome.dywoa.utils.RSAUtils; -import com.rehome.dywoa.utils.UiUtlis; import com.rehome.dywoa.weiget.AutoGridView; -import com.rehome.dywoa.weiget.ConfirmDialog; import com.rehome.dywoa.weiget.ConfirmFaceDialog; import com.yolanda.nohttp.NoHttp; import com.yolanda.nohttp.RequestMethod; @@ -70,7 +57,6 @@ import com.yolanda.nohttp.rest.Request; import com.yolanda.nohttp.rest.Response; import java.io.File; -import java.io.FileOutputStream; import java.net.URLEncoder; import java.text.ParseException; import java.text.SimpleDateFormat; @@ -81,9 +67,6 @@ import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Objects; -import java.util.UUID; - -import cn.hutool.core.io.IoUtil; public class HomeFragment extends BaseFragment { @@ -441,6 +424,17 @@ public class HomeFragment extends BaseFragment { intentEveryDateRiskControllerList.putExtra("type",typeEveryDateRisk); intentEveryDateRiskControllerList.putExtra("urlLog",urlEveryDateRisk); startActivity(intentEveryDateRiskControllerList); + break; + case 13: +// Intent intentBlueTestInfo = new Intent(mActivity, BlueTestInfoActivity.class); +// intentBlueTestInfo.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP); +// startActivity(intentBlueTestInfo); + + Intent intentBlueToothDevice = new Intent(mActivity, BlueToothDeviceActivity.class); + intentBlueToothDevice.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP); + startActivity(intentBlueToothDevice); + + break; } } @@ -498,12 +492,12 @@ public class HomeFragment extends BaseFragment { // String[] titles = {"管控一体化","两票系统", "SIS系统", "机组参数","巡检","点检","运行日志","kks码查询","应急预案","用车","用印","BI"}; // int[] imgIds = {R.drawable.icon_runlog_home,R.drawable.icon_liangpiao, R.drawable.icon_sis_new, R.drawable.icon_gcjd_new,R.drawable.xjgz,R.drawable.icon_dianjian,R.drawable.icon_runlog_home,R.drawable.icon_kks,R.drawable.icon_yjya,R.drawable.icon_use_car,R.drawable.icon_use_seal,R.drawable.icon_bi}; - String[] titles = {"管控一体化","两票系统", "SIS系统", "机组参数","巡检","点检","kks码查询","应急预案","BI","高风险","人脸识别","隐患随手拍","每日作业管控风险清单"}; + String[] titles = {"管控一体化","两票系统", "SIS系统", "机组参数","巡检","点检","kks码查询","应急预案","BI","高风险","人脸识别","隐患随手拍","每日作业管控风险清单","蓝牙传感器"}; int[] imgIds = {R.drawable.icon_gkyth,R.drawable.icon_lpqt, R.drawable.icon_sis_new_first, R.drawable.icon_jzcs_new,R.drawable.icon_qj_new,R.drawable.icon_dj_new, R.drawable.icon_kks_search,R.drawable.icon_yjya,R.drawable.icon_bi, R.drawable.icon_high_risk,R.drawable.icon_face_re,R.drawable.icon_rinhuan_take, - R.drawable.icon_zyfx}; + R.drawable.icon_zyfx,R.drawable.icon_rinhuan_take}; diff --git a/app/src/main/res/layout/activity_blue_tooth_device.xml b/app/src/main/res/layout/activity_blue_tooth_device.xml new file mode 100644 index 0000000..1d581d0 --- /dev/null +++ b/app/src/main/res/layout/activity_blue_tooth_device.xml @@ -0,0 +1,55 @@ + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/activity_bluetoothlist.xml b/app/src/main/res/layout/activity_bluetoothlist.xml new file mode 100644 index 0000000..ebf309d --- /dev/null +++ b/app/src/main/res/layout/activity_bluetoothlist.xml @@ -0,0 +1,53 @@ + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/listitem_device.xml b/app/src/main/res/layout/listitem_device.xml new file mode 100644 index 0000000..a5cbf17 --- /dev/null +++ b/app/src/main/res/layout/listitem_device.xml @@ -0,0 +1,41 @@ + + + + + + + + + + +