• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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![pair request dialog](figures/pair-request-dialog.png)
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