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.

        Log.e("AAA", "222");

        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("dongpuxiao", "连接成功");

                mHandler.sendEmptyMessage(MESSAGE_START_SUCCESS);

            } else if (status == BluetoothProfile.STATE_DISCONNECTED

                    && newState == BluetoothProfile.STATE_DISCONNECTED) {

                intentAction = ACTION_GATT_DISCONNECTED;

                setConnStatus(false);

                Log.e("dongpuxiao", "连接失败");

                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

你可能感兴趣的:(android)