1# Device Pairing 2 3<!--Kit: Connectivity Kit--> 4<!--Subsystem: Communication--> 5<!--Owner: @enjoy_sunshine--> 6<!--Designer: @chengguohong; @tangjia15--> 7<!--Tester: @wangfeng517--> 8<!--Adviser: @zhang_yixin13--> 9 10## Introduction 11This document provides guidance on how to develop profile capabilities for actively pairing and connecting devices. 12 13## How to Develop 14 15### Applying for the Required Permission 16Apply for the **ohos.permission.ACCESS_BLUETOOTH** permission. For details about how to configure and apply for permissions, see [Declaring Permissions](../../security/AccessToken/declare-permissions.md) and [Requesting User Authorization](../../security/AccessToken/request-user-authorization.md). 17 18### Importing Required Modules 19Import the **connection**, **a2dp**, **hfp**, **hid**, **baseProfile**, **constant**, and error code modules. 20```ts 21import { connection, a2dp, hfp, hid, baseProfile, constant } from '@kit.ConnectivityKit'; 22import { BusinessError } from '@kit.BasicServicesKit'; 23``` 24 25### Subscribing to Pairing Status Change Events 26You can subscribe to pairing status change events to obtain the real-time pairing status. Multiple status transitions occur during the pairing process. 27 28Through the [BOND_STATE_BONDED](../../reference/apis-connectivity-kit/js-apis-bluetooth-connection.md#bondstate) event, you can obtain the pairing status of the device that initiates pairing proactively or is paired. 29```ts 30// Define the callback for pairing status changes. 31function onReceiveEvent(data: connection.BondStateParam) { 32 console.info('pair result: '+ JSON.stringify(data)); 33} 34 35try { 36 // Subscribe to pairing status changes. 37 connection.on('bondStateChange', onReceiveEvent); 38} catch (err) { 39 console.error('errCode: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message); 40} 41``` 42 43### Initiating Pairing 44If the pairing status of the target device is [BOND_STATE_INVALID](../../reference/apis-connectivity-kit/js-apis-bluetooth-connection.md#bondstate), the current device can proactively pair with the target device. 45- You can obtain the target device through the device discovery process. For details, see [Bluetooth Discovery](br-discovery-development-guide.md) or [BLE Device Discovery](ble-development-guide.md). 46 47During the pairing process, a dialog box is displayed. The dialog box style varies according to the pairing type. The following figure shows the **Confirm Passkey** dialog box. The pairing can proceed only when the user agrees to the authorization. 48 49 50 51**Figure 1** Bluetooth pairing request dialog box 52```ts 53// Obtain the device address through the device discovery process. 54let device = 'XX:XX:XX:XX:XX:XX'; 55 56try { 57 // Initiate pairing. 58 connection.pairDevice(device).then(() => { 59 console.info('pairDevice'); 60 }, (error: BusinessError) => { 61 console.error('pairDevice: errCode:' + error.code + ',errMessage' + error.message); 62 }); 63} catch (err) { 64 console.error('startPair: errCode:' + err.code + ',errMessage' + err.message); 65} 66``` 67 68### Connecting to the Profile of a Paired Device 69After successful pairing, an application can call [connectAllowedProfiles](../../reference/apis-connectivity-kit/js-apis-bluetooth-connection.md#connectionconnectallowedprofiles16) to connect to the profile supported by the target device. The profile can only be A2DP, HFP, or HID. If you need to use the SPP connection, see [SPP-based Connection and Data Transmission](spp-development-guide.md). 70 71- The Bluetooth subsystem queries and saves all profiles supported by the target device during pairing. 72- After the pairing is complete, the application can call [getRemoteProfileUuids](../../reference/apis-connectivity-kit/js-apis-bluetooth-connection.md#connectiongetremoteprofileuuids12) to query the profiles supported by the target device. If an applicable profile exists, the application can initiate a connection to the profile within 30 seconds after successful pairing. 73```ts 74// Device address of the paired device 75let device = 'XX:XX:XX:XX:XX:XX'; 76 77// Create an A2DP, HFP, or HID instance. 78let a2dpSrc = a2dp.createA2dpSrcProfile(); 79let hfpAg = hfp.createHfpAgProfile(); 80let hidHost = hid.createHidHostProfile(); 81 82// Define the callback for A2DP connection status change events. 83function onA2dpConnectStateChange(data: baseProfile.StateChangeParam) { 84 console.info(`A2DP State: ${JSON.stringify(data)}`); 85} 86 87// Define the callback for HFP connection status change events. 88function onHfpConnectStateChange(data: baseProfile.StateChangeParam) { 89 console.info(`HFP State: ${JSON.stringify(data)}`); 90} 91 92// Define the callback for HID connection status change events. 93function onHidConnectStateChange(data: baseProfile.StateChangeParam) { 94 console.info(`HID State: ${JSON.stringify(data)}`); 95} 96 97try { 98 // Check whether the target device supports the A2DP, HFP, and HID profiles. 99 // Subscribe to connection status change events depending on the supported profile. 100 a2dpSrc.on('connectionStateChange', onA2dpConnectStateChange); 101 hfpAg.on('connectionStateChange', onHfpConnectStateChange); 102 hidHost.on('connectionStateChange', onHidConnectStateChange); 103 104 // Initiate a connection to the profile. 105 connection.connectAllowedProfiles(device).then(() => { 106 console.info('connectAllowedProfiles'); 107 }, (error: BusinessError) => { 108 console.error('errCode:' + error.code + ',errMessage' + error.message); 109 }); 110} catch (err) { 111 console.error('errCode:' + err.code + ',errMessage' + err.message); 112} 113``` 114 115## Sample Code 116```ts 117import { connection, a2dp, hfp, hid, baseProfile, constant } from '@kit.ConnectivityKit'; 118import { BusinessError } from '@kit.BasicServicesKit'; 119 120export class PairDeviceManager { 121 device: string = ''; 122 pairState: connection.BondState = connection.BondState.BOND_STATE_INVALID; 123 a2dpSrc = a2dp.createA2dpSrcProfile(); 124 hfpAg = hfp.createHfpAgProfile(); 125 hidHost = hid.createHidHostProfile(); 126 127 // Define the callback for pairing status change events. 128 onBondStateEvent = (data: connection.BondStateParam) => { 129 console.info('pair result: '+ JSON.stringify(data)); 130 if (data && data.deviceId == this.device) { 131 this.pairState = data.state; // Save the pairing status of the target device. 132 } 133 }; 134 135 // Initiate pairing. The device address can be obtained through the device discovery process. 136 public startPair(device: string) { 137 this.device = device; 138 try { 139 // Subscribe to pairing status change events. 140 connection.on('bondStateChange', this.onBondStateEvent); 141 } catch (err) { 142 console.error('bondStateChange errCode: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message); 143 } 144 145 try { 146 // Initiate pairing. 147 connection.pairDevice(device).then(() => { 148 console.info('pairDevice'); 149 }, (error: BusinessError) => { 150 console.error('pairDevice: errCode:' + error.code + ',errMessage' + error.message); 151 }); 152 } catch (err) { 153 console.error('startPair: errCode:' + err.code + ',errMessage' + err.message); 154 } 155 } 156 157 // Define the callback for A2DP connection status change events. 158 onA2dpConnectStateChange = (data: baseProfile.StateChangeParam) => { 159 console.info(`A2DP State: ${JSON.stringify(data)}`); 160 }; 161 162 // Define the callback for HFP connection status change events. 163 onHfpConnectStateChange = (data: baseProfile.StateChangeParam) => { 164 console.info(`HFP State: ${JSON.stringify(data)}`); 165 }; 166 167 // Define the callback for HID connection status change events. 168 onHidConnectStateChange = (data: baseProfile.StateChangeParam) => { 169 console.info(`HID State: ${JSON.stringify(data)}`); 170 }; 171 172 // Initiate a connection. 173 public async connect(device: string) { 174 try { 175 let uuids = await connection.getRemoteProfileUuids(device); 176 console.info('device: ' + device + ' remoteUuids: '+ JSON.stringify(uuids)); 177 let allowedProfiles = 0; 178 // If an applicable profile exists, enable listening for connection status changes of the profile. 179 if (uuids.some(uuid => uuid == constant.ProfileUuids.PROFILE_UUID_A2DP_SINK.toLowerCase())) { 180 console.info('device supports a2dp'); 181 allowedProfiles++; 182 this.a2dpSrc.on('connectionStateChange', this.onA2dpConnectStateChange); 183 } 184 if (uuids.some(uuid => uuid == constant.ProfileUuids.PROFILE_UUID_HFP_HF.toLowerCase())) { 185 console.info('device supports hfp'); 186 allowedProfiles++; 187 this.hfpAg.on('connectionStateChange', this.onHfpConnectStateChange); 188 } 189 if (uuids.some(uuid => uuid == constant.ProfileUuids.PROFILE_UUID_HID.toLowerCase()) || 190 uuids.some(uuid => uuid == constant.ProfileUuids.PROFILE_UUID_HOGP.toLowerCase())) { 191 console.info('device supports hid'); 192 allowedProfiles++; 193 this.hidHost.on('connectionStateChange', this.onHidConnectStateChange); 194 } 195 if (allowedProfiles > 0) { // If there is an applicable profile, initiate a connection. 196 connection.connectAllowedProfiles(device).then(() => { 197 console.info('connectAllowedProfiles'); 198 }, (error: BusinessError) => { 199 console.error('errCode:' + error.code + ',errMessage' + error.message); 200 }); 201 } 202 } catch (err) { 203 console.error('errCode:' + err.code + ',errMessage' + err.message); 204 } 205 } 206} 207 208let pairDeviceManager = new PairDeviceManager(); 209export default pairDeviceManager as PairDeviceManager; 210``` 211