内容简介:最近做一款Android与蓝牙BLE设备通讯的项目,记录下开发经验。蓝牙设备是JDY-19模块,串口透传,非常方便好用。官方教程需要创建Service进行通讯,此处需求为简单数据透传,直接在Activity中收发完成就结束,不开启服务,简单便捷。话不多说,代码伺候。一次连接需要的数据是扫描后的device对象,连接哪个设备就使用这个device对象进行后续连接
最近做一款Android与蓝牙BLE设备通讯的项目,记录下开发经验。
蓝牙设备是JDY-19模块,串口透传,非常方便好用。官方教程需要创建Service进行通讯,此处需求为简单数据透传,直接在Activity中收发完成就结束,不开启服务,简单便捷。话不多说,代码伺候。
一、Android扫描BLE设备
0. 开启权限
<uses-feature android:name="android.hardware.bluetooth_le" android:required="true" /> <uses-permission android:name="android.permission.BLUETOOTH" /> <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.INTERNET" />
1. 检查是否有BLE支持
if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) { Toast.makeText(this, "您的设备不支持蓝牙BLE", Toast.LENGTH_SHORT).show(); finish(); }
2.检查是否有蓝牙支持
final BluetoothManager bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE); mBluetoothAdapter = bluetoothManager.getAdapter(); if (mBluetoothAdapter == null) { Toast.makeText(this, "您的设备不支持蓝牙", Toast.LENGTH_SHORT).show(); finish(); }
3.如果本地蓝牙没有开启,请求打开
if (!mBluetoothAdapter.isEnabled()) { //两种方式 //1.请求用户打开 // 我们通过startActivityForResult()方法发起的Intent将会在onActivityResult()回调方法中获取用户的选择,比如用户单击了Yes开启, // 那么将会收到RESULT_OK的结果, // 如果RESULT_CANCELED则代表用户不愿意开启蓝牙 Intent mIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE); startActivityForResult(mIntent, REQUEST_ENABLE_BT); // 2.用enable()方法来开启,无需询问用户(无声息的开启蓝牙设备),这时就需要用到android.permission.BLUETOOTH_ADMIN权限。 //mBluetoothAdapter.enable(); // mBluetoothAdapter.disable();//关闭蓝牙 }
4.开始扫描LE设备,这个API要求 targetSdkVersion 必须低于21 , minSdkVersion必须大于等于18
scanLeDevice(true); 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); // } // }, SCAN_PERIOD); // mScanning = true; mBluetoothAdapter.startLeScan(mLeScanCallback); } else { mScanning = false; mBluetoothAdapter.stopLeScan(mLeScanCallback); } }
5.扫描结果
private BluetoothAdapter.LeScanCallback mLeScanCallback = new BluetoothAdapter.LeScanCallback() { @Override public void onLeScan(final BluetoothDevice device, final int rssi, final byte[] scanRecord) { runOnUiThread(new Runnable() { @Override public void run() { for (Map<String, Object> item : mData) { if (item.get("mac").equals(device.getAddress())) { item.put("rssi",rssi); adapter.notifyDataSetChanged(); return; } } Log.i("CTLockBLE", "device found name:" + device.getName() + " mac:" + device.getAddress() + " type:" + device.getType() + " rssi:" + rssi); if (device.getAddress() == null) { return; } if (scanRecord.length != 62 || scanRecord[20 - 6] != (byte) 0xa0) { //不是透传模块 return; } Map<String, Object> itemData = new HashMap<>(); itemData.put("dev",device); itemData.put("name", device.getName()); itemData.put("mac", device.getAddress()); itemData.put("type", device.getType()); itemData.put("rssi", rssi); itemData.put("sr", scanRecord); mData.add(itemData); adapter.notifyDataSetChanged(); } }); } };
6.保存扫描结果
一次连接需要的数据是扫描后的device对象,连接哪个设备就使用这个device对象进行后续连接
二、与蓝牙BLE通讯
package cn.nodemedia.ctlockble; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothGatt; import android.bluetooth.BluetoothGattCallback; import android.bluetooth.BluetoothGattCharacteristic; import android.bluetooth.BluetoothGattDescriptor; import android.bluetooth.BluetoothGattService; import android.bluetooth.BluetoothProfile; import android.content.Context; import android.util.Log; public class BLEControl { public interface BLEControlCallback { void onConnStatus(int status); } private final static String TAG = "CTBLE.BLEControl"; private static final int STATE_DISCONNECTED = 0; private static final int STATE_CONNECTING = 1; private static final int STATE_CONNECTED = 2; public static String Service_uuid = "0000ffe0-0000-1000-8000-00805f9b34fb"; public static String Characteristic_uuid_TX = "0000ffe1-0000-1000-8000-00805f9b34fb"; public static String Characteristic_uuid_RX = "00002902-0000-1000-8000-00805f9b34fb"; public static String Characteristic_uuid_FUNCTION = "0000ffe2-0000-1000-8000-00805f9b34fb"; private Context mContext; private BluetoothDevice mDevice; private BluetoothGatt mBluetoothGatt; private BLEControlCallback mCallback; private int mConnectionState = STATE_DISCONNECTED; private boolean isSubscribe = false; public BLEControl(Context context, BluetoothDevice device, BLEControlCallback callback) { this.mContext = context; this.mDevice = device; this.mCallback = callback; } public int connect() { mConnectionState = STATE_CONNECTING; this.mBluetoothGatt = mDevice.connectGatt(mContext, true, mGattCallback); return this.mBluetoothGatt == null ? -1 : 0; } public void disconnect() { if (mBluetoothGatt != null) { mCallback.onConnStatus(1004); mBluetoothGatt.close(); } } void deley(int ms) { try { Thread.currentThread(); Thread.sleep(ms); } catch (InterruptedException e) { e.printStackTrace(); } } public int updateRom() { return 0; } private final BluetoothGattCallback mGattCallback = new BluetoothGattCallback() { @Override public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) { if (newState == BluetoothProfile.STATE_CONNECTED) { mConnectionState = STATE_CONNECTED; Log.i(TAG, "Connected to GATT server."); Log.i(TAG, "Attempting to start service discovery:" + mBluetoothGatt.discoverServices()); // runOnUiThread(() -> ); mCallback.onConnStatus(1000); } else if (newState == BluetoothProfile.STATE_DISCONNECTED) { mConnectionState = STATE_DISCONNECTED; Log.i(TAG, "Disconnected from GATT server."); // runOnUiThread(() -> stateTv.setText("设备已断开")); mCallback.onConnStatus(1002); } } @Override // New services discovered public void onServicesDiscovered(BluetoothGatt gatt, int status) { if (status == BluetoothGatt.GATT_SUCCESS) { Log.d(TAG, "onServicesDiscovered received: " + status); for (BluetoothGattService service : mBluetoothGatt.getServices()) { Log.d(TAG, "get service uuid " + service.getUuid() + " type:" + service.getType()); for (BluetoothGattCharacteristic gc : service.getCharacteristics()) { Log.d(TAG, "get service gc uuid " + gc.getUuid()); for (BluetoothGattDescriptor descriptor : gc.getDescriptors()) { Log.d(TAG, "get service gc descriptor uuid " + descriptor.getUuid()); isSubscribe = mBluetoothGatt.setCharacteristicNotification(gc, true); if (isSubscribe) { descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE); mBluetoothGatt.writeDescriptor(descriptor); mCallback.onConnStatus(1001); } else { Log.e(TAG, "setCharacteristicNotification error"); mCallback.onConnStatus(1003); } } } } } else { Log.w(TAG, "onServicesDiscovered received: " + status); } } @Override // Result of a characteristic read operation public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) { if (status == BluetoothGatt.GATT_SUCCESS) { Log.d(TAG, "onCharacteristicRead received: " + status); } } @Override public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) { Log.d(TAG, "onCharacteristicChanged " + characteristic.getValue().length); } }; }
0.创建对象
传入Context对象,扫描后得到的device对象,当前Activity类implements BLEControl.BLEControlCallback后的 this指针
bleControl = new BLEControl(this, mDevice, this);
1.实现事件监听器
@Override public void onConnStatus(int status) { Log.d("CTBLE.CommActivity", "OnConnStatus " + status); runOnUiThread(() -> { switch (status) { case 1000: stateTv.setText("设备已连接"); break; case 1001: stateTv.setText("设备已订阅"); break; case 1002: stateTv.setText("设备已断开"); break; case 1003: stateTv.setText("设备订阅失败"); break; case 1004: stateTv.setText("设备已注销"); break; } }); }
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- PHP使用Redis长连接的方法详解
- PHP长连接实现与使用方法详解
- golang实现基于channel的通用连接池详解
- 详解nginx的请求限制(连接限制和请求限制)
- 后端须知:服务器Tomcat 的连接数与线程池详解
- tcp 长连接与短连接
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Python网络编程基础
John Goerzen / 莫迟 等 / 电子工业出版社 / 2007 / 68.00元
《Python网络编程基础》可以作为各层次Python、Web和网络程序的开发人员的参考书,在实际工作中使用书中的技术,效果更佳。一起来看看 《Python网络编程基础》 这本书的介绍吧!