标准蓝牙 UUID
0000xxxx-0000-1000-8000-00805F9B34FB
其中 xxxx 代表自定义部分
例如:
蓝牙串口服务
1101 -- SerialPortServiceClass_UUID
1102 -- LANAccessUsingPPPServiceClass_UUID
拨号网络服务
1103 -- DialupNetworkingServiceClass_UUID
信息同步服务
1104 -- IrMCSyncServiceClass_UUID
文件传输服务
1106 -- OBEXFileTransferServiceClass_UUID
蓝牙传真服务
1111 -- FaxServiceClass_UUID
蓝牙打印服务
1126 -- HCRPrintServiceClass_UUID
个人局域网服务
1115 -- PANUServiceClass_UUID
人机输入服务
1124 -- HumanInterfaceDeviceServiceClass_UUID
1125 -- HardcopyCableReplacementServiceClass_UUID
经典蓝牙的绑定和通信
- 蓝牙的可被搜索和扫描
- 首先我们要绑定后才能正常通信
- 通信我们这里我们是通过socket来传输文件
服务端设置可被搜索/客户端开始扫描
一、服务端设置可被搜索和监听广播
-
首先使能蓝牙
BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); if (!adapter.isEnabled()) { adapter.enable(); }
-
设置可被搜索
通过反射调动的setScanMode
public static void setDiscoverableTimeout() { try { Method setDiscoverableTimeout = BluetoothAdapter.class.getMethod("setDiscoverableTimeout", int.class); setDiscoverableTimeout.setAccessible(true); // Method setScanMode = BluetoothAdapter.class.getMethod("setScanMode", int.class, int.class); Method setScanMode = BluetoothAdapter.class.getMethod("setScanMode", int.class); setScanMode.setAccessible(true); setDiscoverableTimeout.invoke(adapter, 0); // Object state = setScanMode.invoke(adapter, BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE, 300); Object state = setScanMode.invoke(adapter, BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE); Log.d(TAG, "setDiscoverableTimeout setScanMode:" + state); } catch (Exception e) { e.printStackTrace(); Log.e(TAG, "setDiscoverableTimeout failure:" + e.getMessage()); } }
-
服务端监听状态变化广播
二、客户端启动扫描和监听广播
-
首先也要先打开蓝牙(和上面方法相同)
-
开始扫描蓝牙
if (!mBlueAdapter.isDiscovering()) { Log.d(TAG, "startDiscovery"); mBlueAdapter.startDiscovery(); }
-
服务端监听状态变化广播
主要是为了获取绑定状态,连接状态,扫描返回,绑定请求
IntentFilter filter = new IntentFilter(); filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);//蓝牙开关状态 filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED);//蓝牙开始搜索 filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);//蓝牙搜索结束 filter.addAction(BluetoothDevice.ACTION_FOUND);//蓝牙发现新设备(未配对的设备) filter.addAction(BluetoothDevice.ACTION_PAIRING_REQUEST);//在系统弹出配对框之前(确认/输入配对码) filter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED);//设备配对状态改变 filter.addAction(BluetoothDevice.ACTION_ACL_CONNECTED);//最底层连接建立 filter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECTED);//最底层连接断开 filter.addAction(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED); //BluetoothAdapter连接状态 filter.addAction(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED); //BluetoothHeadset连接状态 filter.addAction(BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED); //BluetoothA2dp连接状态 context.registerReceiver(this, filter);
扫描到蓝牙后开始绑定
一、客户创建绑定和确认绑定
-
扫描到蓝牙后–创建绑定
public void onReceive(Context context, Intent intent) { switch (intent.getAction()) { case BluetoothDevice.ACTION_FOUND: // 判断符合自己想要的蓝牙后,创建绑定 BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); creatBond(device.getClass(), device); break; } } private void creatBond(Class bluetoothClass, BluetoothDevice device) { try { Method createBondMethod = bluetoothClass.getMethod("createBond"); Boolean value = (Boolean) createBondMethod.invoke(device); Log.d(TAG, "creatBond return " + value); } catch (NoSuchMethodException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } }
-
配对请求
public void onReceive(Context context, Intent intent) { switch (intent.getAction()) { case BluetoothDevice.ACTION_PAIRING_REQUEST: BluetoothDevice device_bond= intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); int type = intent.getIntExtra(BluetoothDevice.EXTRA_PAIRING_VARIANT, BluetoothDevice.ERROR); int pairingKey = intent.getIntExtra(BluetoothDevice.EXTRA_PAIRING_KEY, BluetoothDevice.ERROR); if (BluetoothDevice.BOND_NONE == type) { abortBroadcast();//终止配对广播,取消系统配对框 // 注意setPairingConfirmation的调用需要系统权限 device.setPairingConfirmation(true); device.setPin(intToByteArray(pairingKey)); } break; } }
二、服务端确认绑定
-
服务端收到广播后绑定
public void onReceive(Context context, Intent intent) { switch (intent.getAction()) { case BluetoothDevice.ACTION_PAIRING_REQUEST: BluetoothDevice device_bond= intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); int type = intent.getIntExtra(BluetoothDevice.EXTRA_PAIRING_VARIANT, BluetoothDevice.ERROR); int pairingKey = intent.getIntExtra(BluetoothDevice.EXTRA_PAIRING_KEY, BluetoothDevice.ERROR); if (BluetoothDevice.BOND_NONE == type) { abortBroadcast();//终止配对广播,取消系统配对框 // 注意setPairingConfirmation的调用需要系统权限 device.setPairingConfirmation(true); device.setPin(intToByteArray(pairingKey)); } break; } }
绑定后开始连接
注意 SPP_UUID 为自定义的 uuid,保持客户端和服务端一致就好
public static final UUID SPP_UUID = UUID.fromString("0000ff01-0000-1000-8000-00805F9B34FB");
一、服务端监听
-
初始化服务端
BluetoothServerSocket mSerSocket = adapter.listenUsingInsecureRfcommWithServiceRecord(TAG, SPP_UUID); //明文传输 BluetoothSocket socket = mSocket.accept(); // 监听连接,阻塞
二、客户端连接
-
创建连接
BluetoothSocket mBlueSocket = mDevice.createInsecureRfcommSocketToServiceRecord(SPP_UUID); try { mBlueSocket.connect(); dataOut = new DataOutputStream(mBlueSocket.getOutputStream()); } catch (IOException e) { e.printStackTrace(); }
-
根据广播收到的连接成功-代表连接成功
数据传输
那么这里就是利用socket传输数据
输出,拿到输出流
dataOut = new DataOutputStream(mBlueSocket.getOutputStream());
读取,拿到输入流
dataIn = new DataInputStream(socket.getInputStream());