BLE是蓝牙4.0核心的profile
弱点是数据传输速率低,由于BLE低功耗特点,因此普遍用于穿戴设备
蓝牙4.0的使用权限
<!--蓝牙4.0需要的权限--> <uses-feature android:name="android.hardware.bluetooth.le" android:required="true"/> <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/> <uses-permission android:name="android.permission.BLUETOOTH"/> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>因为包括模糊定位的危险权限,所以需要进行运行时权限处理
查看手机是否支持蓝牙设备和蓝牙4.0功能
protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); requestPermission(); mToast = Toast.makeText(this,"",Toast.LENGTH_SHORT); //实例化蓝牙适配器BluetoothAdapter final BluetoothManager bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE); mBluetoothAdapter = bluetoothManager.getAdapter(); if(mBluetoothAdapter != null){ showToast("手机支持蓝牙功能!"); }else{ finish(); } if(!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)){ showToast("手机不支持蓝牙BLE功能"); }else{ showToast("手机支持蓝牙BLE功能"); } }
打开蓝牙功能
/** * 在onResume方法中打开蓝牙 */ @Override protected void onResume() { super.onResume(); if(mBluetoothAdapter != null && !mBluetoothAdapter.isEnabled()){ //如果蓝牙适配器不为空,即手机支持蓝牙功能,适配器的可用状态为false,申请打开蓝牙功能 Intent enableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE); startActivity(enableIntent); } }
扫描附近的设备
//扫描所用到的状态变量,默认是没有开始扫描 private boolean mIsScanStart = false; private BluetoothLeScanner mLeScanner; //配置扫描的设置 private ScanSettings mScanSettings;
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); requestPermission(); mToast = Toast.makeText(this,"",Toast.LENGTH_SHORT); final BluetoothManager bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE); mBluetoothAdapter = bluetoothManager.getAdapter(); if(mBluetoothAdapter != null){ showToast("手机支持蓝牙功能!"); }else{ finish(); } if(!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)){ showToast("手机不支持蓝牙BLE功能"); }else{ showToast("手机支持蓝牙BLE功能"); } //mLeScanner大于21才能使用 if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP){ mLeScanner = mBluetoothAdapter.getBluetoothLeScanner(); mScanSettings = new ScanSettings.Builder() .setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY) //设置扫描到的结果回调callback函数的时间 .setReportDelay(3000).build(); } mScanButton = (Button) findViewById(R.id.btu_scan); mScanButton.setOnClickListener(new View.OnClickListener(){ @Override public void onClick(View v) { if(!mIsScanStart){ //如果没有开始,点击开始 mScanButton.setText("停止扫描"); mIsScanStart = true; scan(true); }else{ mScanButton.setText("开始扫描"); mIsScanStart = false; scan(false); } } }); } @TargetApi(23) private void scan(boolean enable){ final ScanCallback scanCallback = new ScanCallback() { @Override public void onScanResult(int callbackType, ScanResult result) { //对于扫描的到结果进行处理 super.onScanResult(callbackType, result); //通过result获取到扫描到的蓝牙设备 BluetoothDevice device = result.getDevice(); Log.e(TAG, "decive name: "+device.getName()+" , device addr: "+device.getAddress()); } }; if(enable){ //开始扫描 mLeScanner.startScan(scanCallback); }else{ //停止扫描 mLeScanner.stopScan(scanCallback); } }
连接蓝牙设备
连接蓝牙设备需要用到BluetoothGatt和BluetoothCallback回调函数,将上述扫描到的设备地址进行保存,方便后面对其连接。
//扫描到的设备地址 private String mBleAddress; //默认没有连接 private boolean mIsConnected = false;
//线程之间通信 private Handler mMainUIHandler = new Handler(){ @Override public void handleMessage(Message msg) { super.handleMessage(msg); int newState = msg.what; if(newState == BluetoothProfile.STATE_CONNECTED){ mIsConnected = true; mConnButton.setText("断开"); showToast("连接成功!"); }else if(newState == BluetoothProfile.STATE_DISCONNECTED){ mIsConnected = false; mConnButton.setText("连接"); showToast("设备已断开!"); } } }; //连接所用到的类 private BluetoothGatt mGatt; private BluetoothGattCallback mGattCallback = new BluetoothGattCallback() { @Override public void onPhyUpdate(BluetoothGatt gatt, int txPhy, int rxPhy, int status) { super.onPhyUpdate(gatt, txPhy, rxPhy, status); } @Override public void onPhyRead(BluetoothGatt gatt, int txPhy, int rxPhy, int status) { super.onPhyRead(gatt, txPhy, rxPhy, status); } @Override public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) { super.onConnectionStateChange(gatt, status, newState); //newState当前的连接状态 mMainUIHandler.sendEmptyMessage(newState); } @Override public void onServicesDiscovered(BluetoothGatt gatt, int status) { super.onServicesDiscovered(gatt, status); } @Override public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) { super.onCharacteristicRead(gatt, characteristic, status); } @Override public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) { super.onCharacteristicWrite(gatt, characteristic, status); } @Override public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) { super.onCharacteristicChanged(gatt, characteristic); } @Override public void onDescriptorRead(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) { super.onDescriptorRead(gatt, descriptor, status); } @Override public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) { super.onDescriptorWrite(gatt, descriptor, status); } @Override public void onReliableWriteCompleted(BluetoothGatt gatt, int status) { super.onReliableWriteCompleted(gatt, status); } @Override public void onReadRemoteRssi(BluetoothGatt gatt, int rssi, int status) { super.onReadRemoteRssi(gatt, rssi, status); } @Override public void onMtuChanged(BluetoothGatt gatt, int mtu, int status) { super.onMtuChanged(gatt, mtu, status); } };
mConnButton = (Button) findViewById(R.id.btu_conn); mConnButton.setOnClickListener(new View.OnClickListener(){ @Override public void onClick(View v) { if(!mIsConnected){ //如果没有连接上,开始连接 connect(); }else{ //如果已经连接上,断开连接 disconnect(); } } });
private boolean connect(){ //获取远程连接的设备 final BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(mBleAddress); //上下文,是否自动连接,连接状态变化的返回调函数 mGatt = device.connectGatt(MainActivity.this,false,mGattCallback); if(mGatt != null){ return true; }else{ return false; } } //断开连接 private void disconnect(){ if(mGatt != null){ mGatt.disconnect(); } }