Android蓝牙4.0BLE开发实现对蓝牙的写入数据和读取数据


代码基本上都是官方的演示,只是通过修改获得自己想要的结果,下面就简单介绍一下自己的理解。

一,扫描BLE设备活动

检查该设备是否支持BLE设备,谷歌在Android4.3才开始支持BLE设备(晕死,很长一段时间都没有一台4.3的设备,看着程序修改了也不能测试!)。

 if(!getPackageManager()。hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)){
            Toast.makeText(this,R.string.ble_not_supported,Toast.LENGTH_SHORT).show();
            完();
        }

初始化获得一个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();
            完();
            返回;
        }
扫描BLE设备,然后添加到ListView控件里面。

private void scanLeDevice(final boolean enable){
        if(enable){
            //在预定义的扫描周期之后停止扫描。
            mHandler.postDelayed(new Runnable(){
                @覆盖
                public void run(){
                    mScanning = false;
                    mBluetoothAdapter.stopLeScan(mLeScanCallback);
                    invalidateOptionsMenu();
                }
            },SCAN_PERIOD);

            mScanning = true;
            mBluetoothAdapter.startLeScan(mLeScanCallback);
        } else {
            mScanning = false;
            mBluetoothAdapter.stopLeScan(mLeScanCallback);
        }
        invalidateOptionsMenu();
    }

二,蓝牙控制的服务BluetoothLeService

在这个服务里面有一个很重要的回调函数BluetoothGattCallback(),蓝牙的数据读取和状态改变都会回调这个函数。

私人最终蓝牙GattCallback mGattCallback = new BluetoothGattCallback(){
        @覆盖
        public void onConnectionStateChange(BluetoothGatt gatt,int status,int newState){
            字符串intentAction;
          //收到设备通知值(设备上报值)
            if(newState == BluetoothProfile.STATE_CONNECTED){
                intentAction = ACTION_GATT_CONNECTED;
                mConnectionState = STATE_CONNECTED;
                broadcastUpdate(intentAction);
                Log.i(TAG,“连接到GATT服务器”);
                //尝试成功连接后发现服务。
                Log.i(TAG,“尝试启动服务发现:”+
                        mBluetoothGatt.discoverServices());

            } else if(newState == BluetoothProfile.STATE_DISCONNECTED){
                intentAction = ACTION_GATT_DISCONNECTED;
                mConnectionState = STATE_DISCONNECTED;
                Log.i(TAG,“断开GATT服务器”);
                broadcastUpdate(intentAction);
            }
        }

        @覆盖
        public void onServicesDiscovered(BluetoothGatt gatt,int status){
            if(status == BluetoothGatt.GATT_SUCCESS){
                broadcastUpdate(ACTION_GATT_SERVICES_DISCOVERED);
            } else {
                Log.w(TAG,“onServicesDiscovered received:”+ status);
                System.out.println(“onServicesDiscovered received:”+ status);
            }
        }

        @覆盖
        public void onCharacteristicRead(BluetoothGatt gatt,
                                         蓝牙功能特点,
                                         int status){
        	//读取到值,在这里读数据
            if(status == BluetoothGatt.GATT_SUCCESS){
                broadcastUpdate(ACTION_DATA_AVAILABLE,特征);
            }
        }

        @覆盖
        public void onCharacteristicChanged(BluetoothGatt gatt,
                                            蓝牙特征特征){
            broadcastUpdate(ACTION_DATA_AVAILABLE,特征);
        }
    };
在官方的演示中还使用到广播,可能是因为人大神写的,要严谨些。我一开始看的时候就得这有点麻烦,跳转的多麻烦。

private void broadcastUpdate(final String action){
        最终意图意图=新意图(动作);
        sendBroadcast(意向);
    }

    private void broadcastUpdate(final String action,
                                 最终蓝牙功能特性){
        最终意图意图=新意图(动作);

        //这是心率测量配置文件的特殊处理。数据解析是
        //按照配置文件规格执行:
        // http://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicViewer.aspx?u=org.bluetooth.characteristic.heart_rate_measurement.xml
        if(UUID_HEART_RATE_MEASUREMENT.equals(characteristic.getUuid())){
            int flag = characteristic.getProperties();
            int format = -1;
            if((flag&0x01)!= 0){
                format = BluetoothGattCharacteristic.FORMAT_UINT16;
                Log.d(TAG,“心率格式UINT16”);
            } else {
                format = BluetoothGattCharacteristic.FORMAT_UINT8;
                Log.d(TAG,“心率格式UINT8”);
            }
            final int heartRate = characteristic.getIntValue(format,1);
            Log.d(TAG,String.format(“Received heart rate:%d”,heartRate));
            intent.putExtra(EXTRA_DATA,String.valueOf(heartRate));
        } else {
            //对于所有其他配置文件,写入以HEX格式化的数据。对于所有的文件,写入十六进制格式的文件
        	//这里读取到数据
            final byte [] data = characteristic.getValue();
            for(int i = 0; i <data.length; i ++){
				System.out.println(“data ......”+ data [i]);
			}
            if(data!= null && data.length> 0){
                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());
                intent.putExtra(EXTRA_DATA,new String(data));
            }
        }
        sendBroadcast(意向);
    }
发送了广播之后就肯定有广播接收器,这个是在控制蓝牙的活动中,后面再说。

还有几个重要的函数比如readCharacteristic(BluetoothGattCharacteristic characteristics)函数,读取蓝牙中数据。

public void readCharacteristic(BluetoothGattCharacteristic characteristics){
        if(mBluetoothAdapter == null || mBluetoothGatt == null){
            Log.w(TAG,“BluetoothAdapter未初始化”);
            返回;
        }
        mBluetoothGatt.readCharacteristic(特性);
    }
有readCharacteristic(BluetoothGattCharacteristic特征)函数,当然就有写特征(BluetoothGattCharacteristic特征),向蓝牙中写入数据。

  public void writeCharacteristic(BluetoothGattCharacteristic characteristics){
        if(mBluetoothAdapter == null || mBluetoothGatt == null){
            Log.w(TAG,“BluetoothAdapter未初始化”);
            返回;
        }
        mBluetoothGatt.writeCharacteristic(特性);
    }
另外在这个服务中还有其他的一些函数例如初始化initialize()函数,连接蓝牙函数connect(final String address),断开蓝牙连接函数disconnect()等
三,蓝牙控制DeviceControlActivity

扫描到蓝牙设备之后就是对蓝牙进行自己需要的控制,比如写数据,读数据,获取设备信息,设备电量等。

在服务中讲到有一个广播,广播接收器就在这个活动中,通过不同的动作做出相应的操作。

注册的几种事件

 私有静态IntentFilter makeGattUpdateIntentFilter(){
        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;
    }

//处理由服务发射的各种事件。处理服务所激发的各种事件
    // ACTION_GATT_CONNECTED:connected to a GATT server。连接一个GATT服务
    // ACTION_GATT_DISCONNECTED:与GATT服务器断开连接。从GATT服务中断开连接
    // ACTION_GATT_SERVICES_DISCOVERED:found GATT services。查找GATT服务
    // ACTION_DATA_AVAILABLE:从设备接收数据。这可能是阅读的结果
    //或通知操作。从服务中接受数据
    BroadcastReceiver mGattUpdateReceiver = new BroadcastReceiver(){
        @覆盖
        public void onReceive(Context context,Intent intent){
            final String action = intent.getAction();
            if(BluetoothLeService.ACTION_GATT_CONNECTED.equals(action)){
                mConnected = true;
                updateConnectionState(R.string.connected);
                invalidateOptionsMenu();
            } else if(BluetoothLeService.ACTION_GATT_DISCONNECTED.equals(action)){
                mConnected = false;
                updateConnectionState(R.string.disconnected);
                invalidateOptionsMenu();
                clearUI();
            } 
            //发现有可支持的服务
            else if(BluetoothLeService.ACTION_GATT_SERVICES_DISCOVERED.equals(action)){
            	//写数据的服务和特征
            	mnotyGattService = mBluetoothLeService.getSupportedGattServices(UUID.fromString(“0000ffe5-0000-1000-8000-00805f9b34fb”));
                特征= mnotyGattService.getCharacteristic(UUID.fromString(“0000ffe9-0000-1000-8000-00805f9b34fb”));
                //读数据的服务和特征
                readMnotyGattService = mBluetoothLeService.getSupportedGattServices(UUID.fromString(“0000ffe0-0000-1000-8000-00805f9b34fb”));
                readCharacteristic = readMnotyGattService.getCharacteristic(UUID.fromString(“0000ffe4-0000-1000-8000-00805f9b34fb”));
            } 
            //显示数据
            else if(BluetoothLeService.ACTION_DATA_AVAILABLE.equals(action)){
            	//将数据显示在mDataField上
            	String data = intent.getStringExtra(BluetoothLeService.EXTRA_DATA);
            	System.out.println(“data ----”+ data);
                displayData(数据);
            }
        }
    };    
在发现了有可支持的服务之后会回调服务中的onServicesDiscovered()函数,并发送广播,在官方的演示中发现了可用的服务之后,就查找该BLE设备支持的所有服务和特性,在这里不需要查找所有的服务,只需要向蓝牙写数据和读取数据的 服务和特征的UUID即可。通过查询低功耗蓝牙(BLE)的数据手册可以得到所需要的UUID。

置顶Android蓝牙4.0BLE开发实现对蓝牙的写入数据和读取数据

有了这两个服务和特征的 UUID,就可以对蓝牙发送数据,并发出通知(当写数据发生改变时发出)。

<span style =“;”> //写数据的服务和特征
            	mnotyGattService = mBluetoothLeService.getSupportedGattServices(UUID.fromString(“0000ffe5-0000-1000-8000-00805f9b34fb”));
                特征= mnotyGattService.getCharacteristic(UUID.fromString(“0000ffe9-0000-1000-8000-00805f9b34fb”));
                //读数据的服务和特征
                readMnotyGattService = mBluetoothLeService.getSupportedGattServices(UUID.fromString(“0000ffe0-0000-1000-8000-00805f9b34fb”));
                readCharacteristic = readMnotyGattService.getCharacteristic(UUID.fromString(“0000ffe4-0000-1000-8000-00805f9b34fb”)); </ span>
得到这两个服务和特性就可以向蓝牙发送数据了。

private void read(){
    	//mBluetoothLeService.readCharacteristic(readCharacteristic);
    	// readCharacteristic的数据发生变化,发出通知
    	mBluetoothLeService.setCharacteristicNotification(readCharacteristic,true);
    	//Toast.makeText(this,“读成功”,Toast.LENGTH_SHORT).show();
	}
检测readCharacteristic的数据发生变化,发出通知。

向蓝牙发送数据。

读();
				
                final int charaProp = characteristic.getProperties();
                
                //如果该字符可写
                if((charaProp | BluetoothGattCharacteristic.PROPERTY_READ)> 0){
                    //如果有关于特征的活动通知,请清除
                    //它首先,所以它不会更新用户界面上的数据字段。
                    if(mNotifyCharacteristic!= null){
                        mBluetoothLeService.setCharacteristicNotification(mNotifyCharacteristic,false);
                        mNotifyCharacteristic = null;
                    }
                    //读取数据,数据将在回调函数中
                    //mBluetoothLeService.readCharacteristic(characteristic);
                    byte [] value = new byte [20];
                    值[0] =(字节)0x00;
                    如果(edittext_input_value.getText()。的toString()。等于( “”)){
                    	Toast.makeText(getApplicationContext(),“请输入!”,Toast.LENGTH_SHORT).show();
                    	返回;
                    }其他{
                    	WriteBytes = edittext_input_value.getText()。toString()。getBytes();
                    	characteristic.setValue(value [0],BluetoothGattCharacteristic.FORMAT_UINT8,0);
                        characteristic.setValue(WriteBytes);
                        mBluetoothLeService.writeCharacteristic(特性);
                        Toast.makeText(getApplicationContext(),“写入成功!”,Toast.LENGTH_SHORT).show();
                    }
                }
                if((charaProp | BluetoothGattCharacteristic.PROPERTY_NOTIFY)> 0){
                    mNotifyCharacteristic =特征;
                    mBluetoothLeService.setCharacteristicNotification(特征,真实);
                }
                edittext_input_value.setText( “”);
			}
一旦数据发生改变,就会发出通知,通知发出后就会调用下面的函数并发出广播。

 @覆盖
        public void onCharacteristicChanged(BluetoothGatt gatt,
                                            蓝牙特征特征){
            broadcastUpdate(ACTION_DATA_AVAILABLE,特征);
        }
Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐