当前位置:   article > 正文

安卓蓝牙开发 1. 发现过程_andriod api 蓝牙可被发现

andriod api 蓝牙可被发现

一、基本概念

蓝牙是一种低功耗、低成本、近距离的无线连接方案,已经经历了2.0、2.1、3.0、4.0、4.2、5.0、5.1、5.2等多个版本迭代。

安卓4.3版本引入了蓝牙支持,可以用于发现设备、查询服务和传输信息。

安卓支持的蓝牙通讯主要是两种:

  1. GATT和ATT 实现与附近的设备传输少量的数据(低功耗蓝牙),主要用在鼠标、键盘、物联网设备通讯。
  2. 传统大数据通讯。

二、 蓝牙发现

安卓开发蓝牙程序一般过程:

Created with Raphaël 2.3.0 设备是否支持蓝牙 蓝牙是否打开? 打开蓝牙 搜索蓝牙设备 连接蓝牙 设备通讯 yes no

三、相关API

  • BluetoothAdapter:本地蓝牙适配器
  • BluetoothDevice:蓝牙设备对象
  • BluetoothProfile:通用的蓝牙规范(数据收发协议)
  • BluetoothGatt:蓝牙通用属性协议,用于连接设备、搜索服务等
  • BluetoothGattCallback:蓝牙连接成功回调函数
  • BluetoothGattService:蓝牙设备提供的服务,它是蓝牙设备特征的集合
  • BluetoothGattCharacteristic:蓝牙设备特征,构建GATT服务的基本单位
  • BluetoothGattDescriptor:蓝牙设备特征描述符,对特征的额外描述。

四、发现的过程

1. 启用权限

<!-- 通用蓝牙权限 -->
<uses-permission android:name="android.permission.BLUETOOTH"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
 
<!-- 位置权限,安卓6.0以上发现过程需要位置权限 -->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

SDK23以上需要添加运行时权限:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M &&
        checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED &&
        checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED &&
        checkSelfPermission(Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED ) {
             requestPermissions(new String[]{Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION ,
            Manifest.permission.CAMERA,}, 1);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

2. 获取BluetoothAdapter

private BluetoothAdapter mBluetoothAdapter;

final BluetoothManager bletoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
mBluetoothAdatper  bluetoothManager.getAdapter();
  • 1
  • 2
  • 3
  • 4

3. 判断蓝牙是否开启

if(mBluetoothAdapter == null || !mBluetoothAdapter.isEnabled()){
   // 如果没有开启,转到用户蓝牙设备界面
   Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
   startActivityForResult(enableBtIntent, 6);
   }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

4. 查找蓝牙设备

以下三种方式可以用来执行查找蓝牙设备的操作。

4.4.1 BluetoothAdapter.startLeScan

BluetoothAdapter的 startLeScan方法用来查找设备。查找过程是一个异步方法,查找完成,通过 实现 BluetoothAdapter.LeScanCallback回调查看查找结果 。
在onLeScan() 中不能做耗时操作,否则容易堵塞。

startLeScan的定义:


public boolean startLeScan(LeScanCallback callback) ;
public boolean startLeScan(final UUID[] serviceUuids, final LeScanCallback callback) ;
  • 1
  • 2
  • 3

可以通过UUID[] 来设置扫描特定类型的外设。

扫描的代码片段:

    private Handler mHandler;

    // 延迟执行的函数,用来限定扫描时间
    mHandler.postDelayed(new Runnable() {
        @Override
        public void run() {
            mScanning = false;
            mBluetoothAdapter.stopLeScan(mLeScanCallback);
        }
    }, 10*1000);

    mScanning = true;
    mBluetoothAdapter.startLeScan(mLeScanCallback);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

4.4.2 getBluetoothLeScanner()

bluetoothAdapter.getBluetoothLeScanner()用来获取一个扫描器,这个扫描器可以设置扫描蓝牙的模式、过滤器等参数。整体来说,与上一种方式区别不大。

           List<ScanFilter> filters = new ArrayList<>();
           ScanFilter filter = new ScanFilter.Builder().setDeviceName("要限定的蓝牙名称").build();
             filters.add(filter);
             ScanSettings scanSettings = new ScanSettings.Builder().setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY).build();

             scanner.startScan(filters, scanSettings, scanCallback);
             Looper.prepare();
             new Handler().postDelayed(() -> {
                 scanner.stopScan(scanCallback);
                 Looper.myLooper().quit();
             }, 30 * 1000L);
             Looper.loop();
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

4.4.3 startDiscovery()方法

这个方法要继承一个BroadcastReceiver的广播,重写其中的onReceive方法。

// 定义 广播接收
class SingBroadcastReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();
        if (BluetoothDevice.ACTION_FOUND.equals(action) ){
            // Get the BluetoothDevice object from the Intent
            BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
            // Add the name and address to an array adapter to show in a Toast
            String derp = device.getName() + " - " + device.getAddress();
            Toast.makeText(context, derp, Toast.LENGTH_LONG).show();
        }
    }
}

// 注册广播、创建SingBroadcastReceiver对象。
SingBroadcastReceiver mReceiver=new SingBroadcastReceiver ();
 mBluetoothAdapter.startDiscovery();
 IntentFilter ifilter1= new IntentFilter(BluetoothDevice.ACTION_FOUND);
  registerReceiver(mReceiver, ifilter1);

// 扫描
mBluetoothAdapter.startDiscovery();
// 停止扫描
mBluetoothAdapter.cancelDiscovery();
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

使用这种方式注意广播要及时关闭。

5. 在查找的回调函数中取得扫描的设备

上面每种扫描方式对应的回调函数有所不同。

4.5.1 使用 BluetoothAdapter.start.LeScan的回调

BluetoothAdapter.LeScanCallback mLeScanCallback = new BluetoothAdapter.LeScanCallback() {
      @Override
      public void onLeScan(final BluetoothDevice device, int rssi, byte[] scanRecord) {
          mArrayAdapter.add(device.getName() + "\n" + device.getAddress());
          lv_bluetooth.setAdapter(mArrayAdapter);
          Log.d(TAG, "onLeScan:563463 ");
      }
  };
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

4.5.2 getBluetoothLeScanner

@Override
            public void onScanResult(int callbackType, ScanResult result) {
                BluetoothDevice device = result.getDevice();
                Log.i(TAG, "蓝牙设备名称:" + device.getName() + ";address=" + device.getAddress());
                super.onScanResult(callbackType, result);
            }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

4.5.3 在前一章节发现的方法中已经定义了回调。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/知新_RL/article/detail/483771
推荐阅读
相关标签
  

闽ICP备14008679号