zoukankan      html  css  js  c++  java
  • android 蓝牙4.0多通道

        很久没记录东西了,前段时间研究了一哈android4.0控制多个外设的情况,注意,需要使用android版本4.3以上,蓝牙4.0及以上。

        我这里使用的控制蓝牙灯泡,使用android4.3的手机,手机上的蓝牙是4.0.

        记得在manifest文件中加入权限:

        

     <uses-permission android:name="android.permission.BLUETOOTH" />
     <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />

        先拿到BluetoothManager和BluetoothAdapter的对象。

        

            // 初始化 Bluetooth adapter, 通过蓝牙管理器得到一个参考蓝牙适配器(API必须在以上android4.3或以上和版本)
            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;
            }

        看下是否开启了蓝牙,如果没有开启,跳转到设置去开启蓝牙。

        

    // 为了确保设备上蓝牙能使用, 如果当前蓝牙设备没启用,弹出对话框向用户要求授予权限来启用
            if (!mBluetoothAdapter.isEnabled()) {
                if (!mBluetoothAdapter.isEnabled()) {
                    Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
                    startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
                }
            }

        调用startScan方法开始扫描,stopScan方法停止扫描,扫描到的设备都在回调函数里。

        

    private void scanLeDevice(final boolean enable) {
            if (enable) {
                // Stops scanning after a pre-defined scan period.
                mHandler.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        mScanning = false;
                        mBluetoothAdapter.stopLeScan(mLeScanCallback);
                        invalidateOptionsMenu();
                    }
                }, SCAN_PERIOD);
    
                mScanning = true;
                mBluetoothAdapter.startLeScan(mLeScanCallback);
            } else {
                mScanning = false;
                mBluetoothAdapter.stopLeScan(mLeScanCallback);
            }
            invalidateOptionsMenu();
        }

        

    // Device scan callback.
        private BluetoothAdapter.LeScanCallback mLeScanCallback = new BluetoothAdapter.LeScanCallback() {
    
            @Override
            public void onLeScan(final BluetoothDevice device, int rssi,
                    byte[] scanRecord) {
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        mLeDeviceListAdapter.addDevice(device);
    //                    mLeDeviceListAdapter.notifyDataSetChanged();
                    }
                });
            }
        };

        扫描后的BluetoothDevice加入到列表中,这时列表中就会有设备,通过getName可以获取设备的蓝牙名字,getAddress获取设备的蓝牙地址。

        列表出来了之后,点击某个设备进行连接。

        注意这里的连接跟2.0的蓝牙的连接不一样,通过设备的connectGatt方法进行连接,连接完成后会获得一个BluetoothGatt的对象,这个对象中有连接的一些重要信息,切记要保存好。

        

    public boolean connect(final String address) {
            if (mBluetoothAdapter == null || address == null) {
                Log.w(TAG, "BluetoothAdapter not initialized or unspecified address.");
                return false;
            }
    
            if (mBluetoothDeviceAddress != null
                    && address.equals(mBluetoothDeviceAddress)
                    && mBluetoothGatt != null) {
                Log.d(TAG,
                        "Trying to use an existing mBluetoothGatt for connection.");
                if (mBluetoothGatt.connect()) {
                    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, true, mGattCallback);
            Log.d(TAG, "Trying to create a new connection.");
            mBluetoothDeviceAddress = address;
            bluetoothGatts.add(mBluetoothGatt);
            return true;
        }

         连接时有一个回调函数mGattCallback,这个函数中有很多设备的相关信息,比如设备的状态啊,设备中的通道哈,一些服务啊之类的。

         

        // 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) {
                System.out.println("onConnectionStateChange");
                String intentAction;
                if (status == BluetoothProfile.STATE_DISCONNECTED
                        && newState == BluetoothProfile.STATE_CONNECTED) {
                    intentAction = ACTION_GATT_CONNECTED;
                    Log.i(TAG, "Connected to GATT server.");
                    // Attempts to discover services after successful connection.
                    Log.i(TAG, "Attempting to start service discovery:"
                            + mBluetoothGatt.discoverServices());
                    Log.e("shang", "连接成功");
                    mHandler.sendEmptyMessage(MESSAGE_START_SUCCESS);
                } else if (status == BluetoothProfile.STATE_DISCONNECTED
                        && newState == BluetoothProfile.STATE_DISCONNECTED) {
                    intentAction = ACTION_GATT_DISCONNECTED;
                    setConnStatus(false);
                    Log.e("shang", "连接失败");
                    Log.i(TAG, "Disconnected from GATT server.");
                    mHandler.sendEmptyMessage(STATE_CONNECTFAILED);
                }
            }
    
            @Override
            public void onServicesDiscovered(BluetoothGatt gatt, int status) {
                System.out.println("onServicesDiscovered-----");
                if (status == BluetoothGatt.GATT_SUCCESS) {
                    broadcastUpdate(ACTION_GATT_SERVICES_DISCOVERED);
                    displayGattServices(getSupportedGattServices());
                    mHandler.sendEmptyMessage(MESSAGE_BLUETOOTH_INIT);
                } else {
                    Log.w(TAG, "onServicesDiscovered received: " + status);
                }
            }
    
            @Override
            public void onCharacteristicRead(BluetoothGatt gatt,
                    BluetoothGattCharacteristic characteristic, int status) {
                System.out.println("onCharacteristicRead");
                if (status == BluetoothGatt.GATT_SUCCESS) {
                    broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic);
                }
            }
    
            @Override
            public void onDescriptorWrite(BluetoothGatt gatt,
                    BluetoothGattDescriptor descriptor, int status) {
    
                System.out.println("onDescriptorWriteonDescriptorWrite = " + status
                        + ", descriptor =" + descriptor.getUuid().toString());
            }
    
            @Override
            public void onCharacteristicChanged(BluetoothGatt gatt,
                    BluetoothGattCharacteristic characteristic) {
                broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic);
                if (characteristic.getValue() != null) {
    
                    System.out.println(characteristic.getStringValue(0));
                }
                System.out.println("--------onCharacteristicChanged-----");
            }
    
            @Override
            public void onReadRemoteRssi(BluetoothGatt gatt, int rssi, int status) {
    
            }
    
            public void onCharacteristicWrite(BluetoothGatt gatt,
                    BluetoothGattCharacteristic characteristic, int status) {
                System.out.println("--------write success----- status:" + status);
            };
        };

        连接时会走这个方法onConnectionStateChange,传过来的新状态是连接状态,这时在这个方法中调用一下这句:mBluetoothGatt.discoverServices(),

        mBluetoothGatt是连接完成时的对象,还记得吧,调用这句后,会走回调函数的onServicesDiscovered方法。在这个方法中去获取设备的一些服务,蓝牙通道,然后通过这些通道去发送数据给外设。

        查看该外设中支持的一些服务通道:

        

    public List<BluetoothGattService> getSupportedGattServices() {
            if (mBluetoothGatt == null)
                return null;
    
            return mBluetoothGatt.getServices();
        }

        

    // Demonstrates how to iterate through the supported GATT
        // Services/Characteristics.
        // In this sample, we populate the data structure that is bound to the
        // ExpandableListView
        // on the UI.
        private void displayGattServices(List<BluetoothGattService> gattServices) {
            if (gattServices == null)
                return;
            String uuid = null;
            ArrayList<HashMap<String, String>> gattServiceData = new ArrayList<HashMap<String, String>>();
            ArrayList<ArrayList<HashMap<String, String>>> gattCharacteristicData = new ArrayList<ArrayList<HashMap<String, String>>>();
            mGattCharacteristics = new ArrayList<ArrayList<BluetoothGattCharacteristic>>();
    
            // Loops through available GATT Services.
            for (BluetoothGattService gattService : gattServices) {
                HashMap<String, String> currentServiceData = new HashMap<String, String>();
                uuid = gattService.getUuid().toString();
                gattServiceData.add(currentServiceData);
    
                ArrayList<HashMap<String, String>> gattCharacteristicGroupData = new ArrayList<HashMap<String, String>>();
                List<BluetoothGattCharacteristic> gattCharacteristics = gattService
                        .getCharacteristics();
                ArrayList<BluetoothGattCharacteristic> charas = new ArrayList<BluetoothGattCharacteristic>();
    
                // Loops through available Characteristics.
                for (BluetoothGattCharacteristic gattCharacteristic : gattCharacteristics) {
                    charas.add(gattCharacteristic);
                    HashMap<String, String> currentCharaData = new HashMap<String, String>();
                    uuid = gattCharacteristic.getUuid().toString();
                    gattCharacteristicGroupData.add(currentCharaData);
                }
                mGattCharacteristics.add(charas);
                gattCharacteristicData.add(gattCharacteristicGroupData);
            }
            bluetoothGattChacteristics.add(mGattCharacteristics);
        }

        然后就可以通过Gatt这个对像,就是蓝牙连接完成后获取到的对象,通过这个对象设置好指定的通道向设备中写入和读取数据。

        写数据:

        

    public void wirteCharacteristic(BluetoothGattCharacteristic characteristic) {
    
            if (mBluetoothAdapter == null || mBluetoothGatt == null) {
                Log.w(TAG, "BluetoothAdapter not initialized");
                return;
            }
    
            mBluetoothGatt.writeCharacteristic(characteristic);
        }

        读数据:

    /**
         * 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;
            }
            mBluetoothGatt.readCharacteristic(characteristic);
        }

        注意:BluetoothGattCharacteristic这个是指定的通道,蓝牙服务:

    BluetoothGattCharacteristic characteristic = null;
    characteristic = mGattCharacteristics.get(4).get(4);

        这两个数字就是从指定的服务中找到你要发送数据的那个服务。

      最后,如果要进行多个连接,每次连接完成后可以将BluetoothGatt的对象放到一个list里面,获取到的服务也放到一个List里面,然后发送数据的时候调用不同的Gatt发送不同的通道数据即可。

       关于蓝牙4.0的BluetoothLeGatt连接,android Samples有一个例子,发上来吧,需要的朋友可以下载看看。

        BluetoothLeGatt

  • 相关阅读:
    sharpen和filter2D
    Changing the contrast and brightness of an image!(opencv对比度和亮度调节)
    人脸表情识别
    Pycharm下载和安装
    Anaconda下载与安装
    图像人脸检测+人眼检测 (opencv + c++)
    cv2.VideoWriter()指定写入视频帧编码格式
    python_openCV例程遇到error: (-215) !empty() in function cv::CascadeClassifier::detectMultiScale的简单解决方法
    图像处理库 Pillow与PIL
    IDE bulid构建隐藏了什么(预处理->编译->汇编->链接)
  • 原文地址:https://www.cnblogs.com/shang53880/p/4624955.html
Copyright © 2011-2022 走看看