• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Using the Call Device Switching Component
2<!--Kit: AVSession Kit-->
3<!--Subsystem: Multimedia-->
4<!--Owner: @ccfriend; @liao_qian-->
5<!--SE: @ccfriend-->
6<!--TSE: @chenmingxi1_huawei-->
7
8## Switching Call Output Devices
9
10The system no longer provides APIs for switching audio output devices. If you need to switch audio output devices within your application, implement the **AVCastPicker** component. For details about the component, see [@ohos.multimedia.avCastPicker](../../reference/apis-avsession-kit/ohos-multimedia-avcastpicker.md) and [@ohos.multimedia.avCastPickerParam](../../reference/apis-avsession-kit/js-apis-avCastPickerParam.md).
11
12This topic describes how to integrate the **AVCastPicker** component to implement the switching of call output devices.
13
14Currently, the system provides the default style and custom style for the **AVCastPicker** component.
15- If the application chooses to display the default style, when the device switches, the system displays the default component style based on the currently selected device.
16- If the application opts for a custom style, it needs to refresh its defined style in response to device changes.
17
18### Implementing the Default Style
19
201. Create an AVSession of the voice_call type. The AVSession constructor provides **AVSessionType** to specify the session type, and **voice_call** indicates the call type. If no AVSession is created, an empty list is displayed.
21
22   ```ts
23    import { avSession } from '@kit.AVSessionKit';
24    @Entry
25    @Component
26    struct Index {
27      @State message: string = 'hello world';
28
29      build() {
30        Column() {
31            Text(this.message)
32              .onClick(()=>{
33                let context = this.getUIContext().getHostContext() as Context;
34                // Create an AVSession of the voice_call type.
35                let session: AVSessionManager.AVSession = await AVSessionManager.createAVSession(context, 'voiptest', 'voice_call');
36              })
37          }
38        .width('100%')
39        .height('100%')
40      }
41    }
42   ```
43
442. Create the **AVCastPicker** component on the call page that provides device switching.
45
46   ```ts
47   import { AVCastPicker } from '@kit.AVSessionKit';
48
49   // Create the component and set its size.
50   build() {
51     Row() {
52       Column() {
53         AVCastPicker()
54           .size({ height:45, width:45 })
55       }
56     }
57   }
58   ```
59
603. Create an AudioRenderer of the VOICE_COMMUNICATION type and start playing. For details about the implementation, see [Developing Audio Call](../audio/audio-call-development.md).
61
62   ```ts
63   import { audio } from '@kit.AudioKit';
64   import { BusinessError } from '@kit.BasicServicesKit';
65
66   private audioRenderer: audio.AudioRenderer | undefined = undefined;
67   private audioStreamInfo: audio.AudioStreamInfo = {
68     // Set the parameters based on project requirements. The following parameters are for reference only.
69     samplingRate: audio.AudioSamplingRate.SAMPLE_RATE_48000, // Sampling rate.
70     channels: audio.AudioChannel.CHANNEL_2, // Channel.
71     sampleFormat: audio.AudioSampleFormat.SAMPLE_FORMAT_S16LE, // Sampling format.
72     encodingType: audio.AudioEncodingType.ENCODING_TYPE_RAW // Encoding format.
73   }
74   private audioRendererInfo: audio.AudioRendererInfo = {
75     // Set the parameters related to the call scenario.
76     usage: audio.StreamUsage.STREAM_USAGE_VIDEO_COMMUNICATION, // Audio stream usage type: VoIP video call, speaker by default.
77     rendererFlags: 0 // AudioRenderer flag. The default value is 0.
78   }
79   private audioRendererOptions: audio.AudioRendererOptions = {
80     streamInfo: this.audioStreamInfo,
81     rendererInfo: this.audioRendererInfo
82   }
83
84   // Create an AudioRenderer instance, and set the events to listen for.
85   try {
86    this.audioRenderer = await audio.createAudioRenderer(this.audioRendererOptions);
87   } catch (err) {
88    console.error(`audioRender create :  Error: ${JSON.stringify(err)}`);
89   }
90
91   this.audioRenderer?.start((err: BusinessError) => {
92    if (err) {
93      console.error(`audioRender start faild :  Error: ${JSON.stringify(err)}`);
94    } else {
95      console.info('audioRender start success');
96    }
97   });
98   ```
99
1004. (Optional) Subscribe to audio output device change events if you want to know the device change status.
101
102   ```ts
103   import { audio } from '@kit.AudioKit';
104
105   let audioManager = audio.getAudioManager(); // Create an AudioManager instance.
106   let audioRoutingManager = audioManager.getRoutingManager(); // Call an API of AudioManager to create an AudioRoutingManager instance.
107
108   // (Optional) Listen for audio output device changes.
109   audioRoutingManager.on('preferOutputDeviceChangeForRendererInfo', this.audioRendererInfo, (desc: audio.AudioDeviceDescriptors) => {
110     console.info(`device change To : ${desc[0].deviceType}`); // Device type.
111   });
112   ```
113
1145. Destroy the AVSession when the call ends.
115
116   ```ts
117   // Destroy the AVSession created in step 1 when the call ends.
118   this.session?.destroy((err) => {
119     if (err) {
120       console.error(`Failed to destroy session. Code: ${err.code}, message: ${err.message}`);
121     } else {
122       console.info(`Destroy : SUCCESS `);
123     }
124   });
125   ```
126
127### Implementing a Custom Style
128
129You can customize a style by setting the **customPicker** parameter of the [CustomBuilder](../../reference/apis-avsession-kit/ohos-multimedia-avcastpicker.md) type.
130
131The procedure for implementing a custom style is similar to that for implementing the default style. You can create an AVSession and implement audio playback by referring to [Implementing the Default Style Implementation](#implementing-the-default-style).
132
133The differences are as follows:
134
1351. When creating a custom **AVCastPicker** component, you must add a custom parameter. (This step corresponds to step 2 in the default style implementation.)
136
137   ```ts
138   import { AVCastPicker } from '@kit.AVSessionKit';
139
140   @State pickerImage:ResourceStr = $r('app.media.earpiece'); // Custom resources.
141
142   build() {
143     Row() {
144       Column() {
145         AVCastPicker(
146           {
147             customPicker: (): void => this.ImageBuilder() // Add a custom parameter.
148           }
149         ).size({ height: 45, width:45 })
150       }
151     }
152   }
153
154   // Custom content.
155   @Builder
156   ImageBuilder(): void {
157     Image(this.pickerImage)
158       .size({ width: '100%', height: '100%' })
159       .backgroundColor('#00000000')
160       .fillColor(Color.Black)
161   }
162   ```
163
1642. If the application needs to change the custom style based on audio output device changes, the application must listen for device change events and refresh the custom style in real time. (This step corresponds to step 4 in the default style implementation.)
165
166   ```ts
167   import { audio } from '@kit.AudioKit';
168
169   async observerDevices() {
170     let audioManager = audio.getAudioManager();
171     let audioRoutingManager = audioManager.getRoutingManager();
172
173     // When the AVCastPicker component is started for the first time, obtain the current device and refresh the content displayed.
174     this.changePickerShow(audioRoutingManager.getPreferredOutputDeviceForRendererInfoSync(this.audioRendererInfo));
175
176     // Listen for the switching of the audio output device and display different styles based on the device type.
177     audioRoutingManager.on('preferOutputDeviceChangeForRendererInfo', this.audioRendererInfo, (desc: audio.AudioDeviceDescriptors) => {
178       this.changePickerShow(audioRoutingManager.getPreferredOutputDeviceForRendererInfoSync(this.audioRendererInfo));
179     });
180   }
181
182   // Refresh the custom resource pickerImage after the device is changed.
183   private changePickerShow(desc: audio.AudioDeviceDescriptors) {
184     if (desc[0].deviceType === 2) {
185       this.pickerImage = $r('app.media.sound');
186     } else if (desc[0].deviceType === 7) {
187       this.pickerImage = $r('app.media.bluetooth');
188     } else {
189       this.pickerImage = $r('app.media.earpiece');
190     }
191   }
192   ```
193
194## Switching Call Input Devices (for PCs and 2-in-1 Devices Only)
195
196The system no longer provides APIs for switching audio input devices. If you need to switch audio input devices within your application, implement the **AVInputCastPicker** component. For details about the component, see [@ohos.multimedia.avInputCastPicker](../../reference/apis-avsession-kit/ohos-multimedia-avinputcastpicker.md) and [@ohos.multimedia.avCastPickerParam](../../reference/apis-avsession-kit/js-apis-avCastPickerParam.md).
197
198This topic describes how to integrate the **AVInputCastPicker** component to implement the switching of call input devices.
199
200Currently, the system provides the default style and custom style for the **AVCastPicker** component.
201- If the application chooses to display the default style, when the device switches, the system displays the default component style based on the currently selected device.
202- If the application opts for a custom style, it needs to refresh its defined style in response to device changes.
203
204### Implementing the Default Style
205
2061. Create the **AVInputCastPicker** component on the call page that provides device switching.
207
208   ```ts
209   import { AVCastPickerState, AVInputCastPicker } from '@kit.AVSessionKit';
210
211   // (Optional) Callback for the device list state change.
212   private onStateChange(state: AVCastPickerState) {
213     if (state == AVCastPickerState.STATE_APPEARING) {
214       console.info('The picker starts showing.');
215     } else if (state == AVCastPickerState.STATE_DISAPPEARING) {
216       console.info('The picker finishes presenting.');
217     }
218   }
219
220   // Create the component and set its size.
221   build() {
222     Row() {
223       Column() {
224         AVInputCastPicker(
225         {
226           onStateChange: this.onStateChange
227         }
228         ).size({ height:45, width:45 })
229       }
230     }
231   }
232   ```
233
2342. Implement the call feature. For details, see [Developing Audio Call](../audio/audio-call-development.md).
235
236### Implementing a Custom Style
237
238You can customize a style by setting the **customPicker** parameter of the [AVInputCastPicker](../../reference/apis-avsession-kit/ohos-multimedia-avinputcastpicker.md#avinputcastpicker).
239
2401. When creating a custom **AVInputCastPicker** component, you must add a custom parameter.
241
242   ```ts
243   import { AVCastPickerState, AVInputCastPicker } from '@kit.AVSessionKit';
244
245   @State pickerImage: ResourceStr = $r('app.media.earpiece'); // Custom resources.
246
247   // (Optional) Callback for the device list state change.
248   private onStateChange(state: AVCastPickerState) {
249     if (state == AVCastPickerState.STATE_APPEARING) {
250       console.info('The picker starts showing.');
251     } else if (state == AVCastPickerState.STATE_DISAPPEARING) {
252       console.info('The picker finishes presenting.');
253     }
254   }
255
256   build() {
257     Row() {
258       Column() {
259         AVInputCastPicker(
260           {
261             customPicker: (): void => this.ImageBuilder(), // Add a custom parameter.
262             onStateChange: this.onStateChange
263           }
264         ).size({ height: 45, width:45 })
265       }
266     }
267   }
268
269   // Custom content.
270   @Builder
271   ImageBuilder(): void {
272     Image(this.pickerImage)
273       .size({ width: '100%', height: '100%' })
274       .backgroundColor('#00000000')
275       .fillColor(Color.Black)
276   }
277   ```
278
2792. Implement the call feature. For details, see [Developing Audio Call](../audio/audio-call-development.md).
280