风澜松叶 發表於 2021-10-26 10:16:00

Android 蓝牙开发

<h2>Android 蓝牙开发</h2>
<p>我们在进行蓝牙开发时首先要了解低功耗蓝牙、经典蓝牙、单模蓝牙、双模蓝牙之间的关系。<br>单模蓝牙:支持低功耗蓝牙<br>双模蓝牙:支持低功耗蓝牙和经典蓝牙<br>经典蓝牙:支持经典蓝牙<br>蓝牙开发大致分为这几步<br><br></p>
<p>前面需要定位权限和蓝牙权限的支持</p>
<p><span style="font-size: 16px"><strong>发现设备:</strong></span></p>
<p>经典蓝牙发现设备api<br>BluetoothAdapter.startDiscovery<br>听说可以同时发现经典蓝牙和低功耗蓝牙(BLE)。但我这没单模的蓝牙,所以没办法测试。<br>因为startDiscovery返回的是一个是否开始扫描设备,我们要获取蓝牙设备的信息需要注册一个 BroadcastReceiver 针对 ACTION_FOUND&nbsp;<br>Intent 会携带额外的字段 EXTRA_DEVICE 和 EXTRA_CLASS。这两者分别包含 BluetoothDevice 和 BluetoothClass。</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">var</span> filter =<span style="color: rgba(0, 0, 0, 1)">IntentFilter(BluetoothDevice.ACTION_FOUND);
registerReceiver(mReceiver,filter);
   
    val mReceiver </span>=<span style="color: rgba(0, 0, 0, 1)"> object :BroadcastReceiver(){
      override fun onReceive(context: Context</span>?, intent: Intent?<span style="color: rgba(0, 0, 0, 1)">) {
            </span><span style="color: rgba(0, 0, 255, 1)">var</span> action = intent?<span style="color: rgba(0, 0, 0, 1)">.action
            </span><span style="color: rgba(0, 0, 255, 1)">if</span>(BluetoothDevice.ACTION_FOUND ==<span style="color: rgba(0, 0, 0, 1)"> action){
                </span><span style="color: rgba(0, 0, 255, 1)">var</span> device = intent?.getParcelableExtra&lt;BluetoothDevice&gt;<span style="color: rgba(0, 0, 0, 1)">(BluetoothDevice.EXTRA_DEVICE)
            }
      }

    }
    override fun onDestroy() {
      super.onDestroy()
      unregisterReceiver(mReceiver)
    }    </span></pre>
</div>
<p>Ble发现设备api<br>BluetoothAdapter.getBluetoothLeScanner()<br>BluetoothLeScanner.startScan(ScanCallback callback)//扫描会在屏幕关闭时停止以节省电量。 再次打开屏幕时,将恢复扫描。 为避免这种情况,请使用下面两个<br>BluetoothLeScanner.startScan(List&lt;ScanFilter&gt; filters, ScanSettings settings, ScanCallback callback)<br>BluetoothLeScanner.startScan(List&lt;ScanFilter&gt; filters, ScanSettings settings, PendingIntent callbackIntent)</p>
<div class="cnblogs_code">
<pre>BluetoothLeScanner bluetoothLeScanner =<span style="color: rgba(0, 0, 0, 1)"> bluetoothAdapter.getBluetoothLeScanner();
      filters.add(</span><span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> ScanFilter.Builder()
                .setServiceUuid(ParcelUuid.fromString(</span>"0000000-0000-0000-0000-000000000000"<span style="color: rgba(0, 0, 0, 1)">))
                .build());
      bluetoothLeScanner.startScan(filters , </span><span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> ScanSettings.Builder().build(),
                </span><span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> ScanCallback() {
                  @Override
                  </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span> onScanResult(<span style="color: rgba(0, 0, 255, 1)">int</span><span style="color: rgba(0, 0, 0, 1)"> callbackType, ScanResult result) {
                        </span><span style="color: rgba(0, 0, 255, 1)">super</span><span style="color: rgba(0, 0, 0, 1)">.onScanResult(callbackType, result);
                        </span><span style="color: rgba(0, 0, 255, 1)">if</span> (Build.VERSION.SDK_INT &gt;=<span style="color: rgba(0, 0, 0, 1)"> Build.VERSION_CODES.O) {
                            Log.d(MainActivity.ACTIVITY_SERVICE, </span>"onScanResult:"+
                              "\n Rssi() "+result.getRssi()+
                              "\n AdvertisingSid() "+result.getAdvertisingSid()+
                              "\n DataStatus() "+result.getDataStatus()+
                              "\n ScanRecord() "+result.getScanRecord().getBytes()+
                              "\n Address() "+result.getDevice().getAddress()+
                              "\n Address() "+<span style="color: rgba(0, 0, 0, 1)">result.getDevice().getName()
                              );
                        }
                  }

                  @Override
                  </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span> onBatchScanResults(List&lt;ScanResult&gt;<span style="color: rgba(0, 0, 0, 1)"> results) {
                        </span><span style="color: rgba(0, 0, 255, 1)">super</span><span style="color: rgba(0, 0, 0, 1)">.onBatchScanResults(results);
                  }

                  @Override
                  </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span> onScanFailed(<span style="color: rgba(0, 0, 255, 1)">int</span><span style="color: rgba(0, 0, 0, 1)"> errorCode) {
                        </span><span style="color: rgba(0, 0, 255, 1)">super</span><span style="color: rgba(0, 0, 0, 1)">.onScanFailed(errorCode);
                  }
                }
      );</span></pre>
</div>
<p>&nbsp;</p>
<p><span style="font-size: 16px"><strong>建立连接:</strong></span></p>
<p>在配对之前应该先cancelDiscovery()或者stopScan(callback),<br>然后根据获取到蓝牙Mac地址连接即可</p>
<div class="cnblogs_code">
<pre>BluetoothDevice device =<span style="color: rgba(0, 0, 0, 1)"> bluetoothAdapter.getRemoteDevice(result.getDevice().getAddress());
device.connectGatt(MainActivity.</span><span style="color: rgba(0, 0, 255, 1)">this</span>, <span style="color: rgba(0, 0, 255, 1)">false</span>, <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> BluetoothGattCallback() {
      @Override
      </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span> onConnectionStateChange(BluetoothGatt gatt, <span style="color: rgba(0, 0, 255, 1)">int</span> status, <span style="color: rgba(0, 0, 255, 1)">int</span><span style="color: rgba(0, 0, 0, 1)"> newState) {
            </span><span style="color: rgba(0, 0, 255, 1)">super</span><span style="color: rgba(0, 0, 0, 1)">.onConnectionStateChange(gatt, status, newState);
            </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">status 连接或断开连接操作成功 BluetoothGatt.GATT_SUCCESS(0)
            </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">newState 新的连接状态 BluetoothProfile.STATE_DISCONNECTED(0-断开状态) BluetoothProfile.STATE_CONNECTED(1-连接状态)</span>
<span style="color: rgba(0, 0, 0, 1)">      }
    }
);</span></pre>
</div>
<p>&nbsp;</p>
<p><strong><span style="font-size: 16px">数据通信:<br></span></strong>ble写入操作</p>
<div class="cnblogs_code">
<pre> <span style="color: rgba(0, 0, 255, 1)">private</span> BluetoothGattCallback bluetoothGattCallback = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> BluetoothGattCallback() {
      @Override
      </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span> onConnectionStateChange(BluetoothGatt gatt, <span style="color: rgba(0, 0, 255, 1)">int</span> status, <span style="color: rgba(0, 0, 255, 1)">int</span><span style="color: rgba(0, 0, 0, 1)"> newState) {
            </span><span style="color: rgba(0, 0, 255, 1)">super</span><span style="color: rgba(0, 0, 0, 1)">.onConnectionStateChange(gatt, status, newState);
            </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">status 连接或断开连接操作成功 BluetoothGatt.GATT_SUCCESS(0)
            </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">newState 新的连接状态 BluetoothProfile.STATE_DISCONNECTED(0-断开状态) BluetoothProfile.STATE_CONNECTED(1-连接状态)
            </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">获取远程设备提供的服务以及它们的特征和描述符。这步很重要而且是一个异步操作(这里需要时间直接接在下面写不可取)</span>
<span style="color: rgba(0, 0, 0, 1)">            bluetoothGatt.discoverServices();
            </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">获取蓝牙GATT服务</span>
            BluetoothGattService gattService = bluetoothGatt.getService(UUID.fromString("00000000-0000-0000-0000-000000000000"<span style="color: rgba(0, 128, 0, 1)">/*</span><span style="color: rgba(0, 128, 0, 1)">蓝牙协议</span><span style="color: rgba(0, 128, 0, 1)">*/</span><span style="color: rgba(0, 0, 0, 1)">));
            </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">GATT特性:用于构建 GATT 服务的基本数据元素</span>
            BluetoothGattCharacteristic characteristic = gattService.getCharacteristic(UUID.fromString("00000000-0000-0000-0000-000000000000"<span style="color: rgba(0, 0, 0, 1)">));
            </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">设置数据,这里是我加密后的数据所以看起来有点不习惯</span>
            <span style="color: rgba(0, 0, 255, 1)">byte</span>[] data = {-27, 36, 65, -70, -8, 94, 18, -12, -56, 116, -68, -124, 92, -19, 94, -91<span style="color: rgba(0, 0, 0, 1)"> };
            </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">设置此特性的本地存储值。</span>
<span style="color: rgba(0, 0, 0, 1)">            characteristic.setValue(data);
            </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">写入到远程蓝牙设备</span>
<span style="color: rgba(0, 0, 0, 1)">            bluetoothGatt.writeCharacteristic(characteristic);
                  
      

      }</span></pre>
</div>
<p>&nbsp;Ble通知读取操作</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">通知UUID</span>
BluetoothGattCharacteristic gattCharacteristic = gattService.getCharacteristic(UUID.fromString("00000000-0000-0000-0000-000000000000"<span style="color: rgba(0, 0, 0, 1)">));
enableNotification(bluetoothGatt,</span><span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">,gattCharacteristic);

</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span> enableNotification(BluetoothGatt bluetoothGatt, <span style="color: rgba(0, 0, 255, 1)">boolean</span><span style="color: rgba(0, 0, 0, 1)"> enable, BluetoothGattCharacteristic characteristic) {
            </span><span style="color: rgba(0, 0, 255, 1)">if</span> (bluetoothGatt == <span style="color: rgba(0, 0, 255, 1)">null</span> || characteristic == <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">) {
                </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)">;
            }
            </span><span style="color: rgba(0, 0, 255, 1)">if</span> (!<span style="color: rgba(0, 0, 0, 1)">bluetoothGatt.setCharacteristicNotification(characteristic, enable)) {
                </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)">;
            }
            </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">获取到Notify当中的Descriptor通道然后再进行注册</span>
            List&lt;BluetoothGattDescriptor&gt; clientConfigs =<span style="color: rgba(0, 0, 0, 1)"> characteristic.getDescriptors();
            </span><span style="color: rgba(0, 0, 255, 1)">if</span> (clientConfigs == <span style="color: rgba(0, 0, 255, 1)">null</span> || clientConfigs.size() ==0<span style="color: rgba(0, 0, 0, 1)">) {
                </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)">;
            }
            </span><span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> (enable) {
                </span><span style="color: rgba(0, 0, 255, 1)">for</span><span style="color: rgba(0, 0, 0, 1)"> (BluetoothGattDescriptor clientConfig: clientConfigs) {
                  clientConfig.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
                  bluetoothGatt.writeDescriptor(clientConfig);
                }
            } </span><span style="color: rgba(0, 0, 255, 1)">else</span><span style="color: rgba(0, 0, 0, 1)"> {
                </span><span style="color: rgba(0, 0, 255, 1)">for</span><span style="color: rgba(0, 0, 0, 1)"> (BluetoothGattDescriptor clientConfig: clientConfigs) {
                  clientConfig.setValue(BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE);
                  bluetoothGatt.writeDescriptor(clientConfig);
                }
            }
      }</span></pre>
</div>
<p>&nbsp;</p><br><br>
来源:https://www.cnblogs.com/javaktolin/p/15459732.html
頁: [1]
查看完整版本: Android 蓝牙开发