1e41f4b71Sopenharmony_ci# Using the Call Device Switching Component 2e41f4b71Sopenharmony_ci 3e41f4b71Sopenharmony_ci## Basic Concepts 4e41f4b71Sopenharmony_ci 5e41f4b71Sopenharmony_ciThe system no longer provides APIs for switching audio output devices. To switch an audio output device, you must 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). 6e41f4b71Sopenharmony_ci 7e41f4b71Sopenharmony_ciThis topic describes how to integrate the **AVCastPicker** component to implement the switching of call devices. 8e41f4b71Sopenharmony_ci 9e41f4b71Sopenharmony_ciCurrently, the system provides the default style and custom style for the **AVCastPicker** component. In the default style, the system displays the default component style based on the selected device during device switching. In the custom style, the application must refresh the style based on the device changes. 10e41f4b71Sopenharmony_ci 11e41f4b71Sopenharmony_ci## How to Develop 12e41f4b71Sopenharmony_ci 13e41f4b71Sopenharmony_ci### Implementing the Default Style 14e41f4b71Sopenharmony_ci 15e41f4b71Sopenharmony_ci1. 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. 16e41f4b71Sopenharmony_ci 17e41f4b71Sopenharmony_ci ```ts 18e41f4b71Sopenharmony_ci import { avSession } from '@kit.AVSessionKit'; 19e41f4b71Sopenharmony_ci 20e41f4b71Sopenharmony_ci private session: avSession.AVSession | undefined = undefined; 21e41f4b71Sopenharmony_ci 22e41f4b71Sopenharmony_ci // Create an AVSession of the voice_call type. 23e41f4b71Sopenharmony_ci this.session = await avSession.createAVSession(getContext(this), 'voiptest', 'voice_call'); 24e41f4b71Sopenharmony_ci ``` 25e41f4b71Sopenharmony_ci 26e41f4b71Sopenharmony_ci2. Create the **AVCastPicker** component on the call page that provides device switching. 27e41f4b71Sopenharmony_ci 28e41f4b71Sopenharmony_ci ```ts 29e41f4b71Sopenharmony_ci import { AVCastPicker } from '@kit.AVSessionKit'; 30e41f4b71Sopenharmony_ci 31e41f4b71Sopenharmony_ci // Create the component and set its size. 32e41f4b71Sopenharmony_ci build() { 33e41f4b71Sopenharmony_ci Row() { 34e41f4b71Sopenharmony_ci Column() { 35e41f4b71Sopenharmony_ci AVCastPicker() 36e41f4b71Sopenharmony_ci .size({ height:45, width:45 }) 37e41f4b71Sopenharmony_ci } 38e41f4b71Sopenharmony_ci } 39e41f4b71Sopenharmony_ci } 40e41f4b71Sopenharmony_ci ``` 41e41f4b71Sopenharmony_ci 42e41f4b71Sopenharmony_ci3. 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). 43e41f4b71Sopenharmony_ci 44e41f4b71Sopenharmony_ci ```ts 45e41f4b71Sopenharmony_ci import { audio } from '@kit.AudioKit'; 46e41f4b71Sopenharmony_ci import { BusinessError } from '@kit.BasicServicesKit'; 47e41f4b71Sopenharmony_ci 48e41f4b71Sopenharmony_ci private audioRenderer: audio.AudioRenderer | undefined = undefined; 49e41f4b71Sopenharmony_ci private audioStreamInfo: audio.AudioStreamInfo = { 50e41f4b71Sopenharmony_ci // Set the parameters based on project requirements. The following parameters are for reference only. 51e41f4b71Sopenharmony_ci samplingRate: audio.AudioSamplingRate.SAMPLE_RATE_48000, // Sampling rate. 52e41f4b71Sopenharmony_ci channels: audio.AudioChannel.CHANNEL_2, // Channel. 53e41f4b71Sopenharmony_ci sampleFormat: audio.AudioSampleFormat.SAMPLE_FORMAT_S16LE, // Sampling format. 54e41f4b71Sopenharmony_ci encodingType: audio.AudioEncodingType.ENCODING_TYPE_RAW // Encoding format. 55e41f4b71Sopenharmony_ci } 56e41f4b71Sopenharmony_ci private audioRendererInfo: audio.AudioRendererInfo = { 57e41f4b71Sopenharmony_ci // Set the parameters related to the call scenario. 58e41f4b71Sopenharmony_ci usage: audio.StreamUsage.STREAM_USAGE_VOICE_COMMUNICATION, // Audio stream usage type: VoIP call. 59e41f4b71Sopenharmony_ci rendererFlags: 0 // AudioRenderer flag. The default value is 0. 60e41f4b71Sopenharmony_ci } 61e41f4b71Sopenharmony_ci private audioRendererOptions: audio.AudioRendererOptions = { 62e41f4b71Sopenharmony_ci streamInfo: this.audioStreamInfo, 63e41f4b71Sopenharmony_ci rendererInfo: this.audioRendererInfo 64e41f4b71Sopenharmony_ci } 65e41f4b71Sopenharmony_ci 66e41f4b71Sopenharmony_ci // Create an AudioRenderer instance, and set the events to listen for. 67e41f4b71Sopenharmony_ci try { 68e41f4b71Sopenharmony_ci this.audioRenderer = await audio.createAudioRenderer(this.audioRendererOptions); 69e41f4b71Sopenharmony_ci } catch (err) { 70e41f4b71Sopenharmony_ci console.error(`audioRender create : Error: ${JSON.stringify(err)}`); 71e41f4b71Sopenharmony_ci } 72e41f4b71Sopenharmony_ci 73e41f4b71Sopenharmony_ci this.audioRenderer?.start((err: BusinessError) => { 74e41f4b71Sopenharmony_ci if (err) { 75e41f4b71Sopenharmony_ci console.error(`audioRender start faild : Error: ${JSON.stringify(err)}`); 76e41f4b71Sopenharmony_ci } else { 77e41f4b71Sopenharmony_ci console.error('audioRender start success'); 78e41f4b71Sopenharmony_ci } 79e41f4b71Sopenharmony_ci }); 80e41f4b71Sopenharmony_ci ``` 81e41f4b71Sopenharmony_ci 82e41f4b71Sopenharmony_ci4. (Optional) Subscribe to audio output device change events if you want to know the device change status. 83e41f4b71Sopenharmony_ci 84e41f4b71Sopenharmony_ci ```ts 85e41f4b71Sopenharmony_ci import { audio } from '@kit.AudioKit'; 86e41f4b71Sopenharmony_ci 87e41f4b71Sopenharmony_ci let audioManager = audio.getAudioManager(); // Create an AudioManager instance. 88e41f4b71Sopenharmony_ci let audioRoutingManager = audioManager.getRoutingManager(); // Call an API of AudioManager to create an AudioRoutingManager instance. 89e41f4b71Sopenharmony_ci 90e41f4b71Sopenharmony_ci // (Optional) Listen for audio output device changes. 91e41f4b71Sopenharmony_ci audioRoutingManager.on('preferOutputDeviceChangeForRendererInfo', this.audioRendererInfo, (desc: audio.AudioDeviceDescriptors) => { 92e41f4b71Sopenharmony_ci console.info(`device change To : ${desc[0].deviceType}`); // Device type. 93e41f4b71Sopenharmony_ci }); 94e41f4b71Sopenharmony_ci ``` 95e41f4b71Sopenharmony_ci 96e41f4b71Sopenharmony_ci5. Destroy the AVSession when the call ends. 97e41f4b71Sopenharmony_ci 98e41f4b71Sopenharmony_ci ```ts 99e41f4b71Sopenharmony_ci // Destroy the AVSession created in step 1 when the call ends. 100e41f4b71Sopenharmony_ci this.session?.destroy((err) => { 101e41f4b71Sopenharmony_ci if (err) { 102e41f4b71Sopenharmony_ci console.error(`Failed to destroy session. Code: ${err.code}, message: ${err.message}`); 103e41f4b71Sopenharmony_ci } else { 104e41f4b71Sopenharmony_ci console.info(`Destroy : SUCCESS `); 105e41f4b71Sopenharmony_ci } 106e41f4b71Sopenharmony_ci }); 107e41f4b71Sopenharmony_ci ``` 108e41f4b71Sopenharmony_ci 109e41f4b71Sopenharmony_ci### Implementing a Custom Style 110e41f4b71Sopenharmony_ci 111e41f4b71Sopenharmony_ciYou can customize a style by setting the **customPicker** parameter of the [CustomBuilder](../../reference/apis-avsession-kit/ohos-multimedia-avcastpicker.md) type. 112e41f4b71Sopenharmony_ci 113e41f4b71Sopenharmony_ciThe 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). 114e41f4b71Sopenharmony_ci 115e41f4b71Sopenharmony_ciThe differences are as follows: 116e41f4b71Sopenharmony_ci 117e41f4b71Sopenharmony_ci1. When creating a custom **AVCastPicker** component, you must add a custom parameter. (This step corresponds to step 2 in the default style implementation.) 118e41f4b71Sopenharmony_ci 119e41f4b71Sopenharmony_ci ```ts 120e41f4b71Sopenharmony_ci import { AVCastPicker } from '@kit.AVSessionKit'; 121e41f4b71Sopenharmony_ci 122e41f4b71Sopenharmony_ci @State pickerImage:ResourceStr = $r('app.media.earpiece'); // Custom resources. 123e41f4b71Sopenharmony_ci 124e41f4b71Sopenharmony_ci build() { 125e41f4b71Sopenharmony_ci Row() { 126e41f4b71Sopenharmony_ci Column() { 127e41f4b71Sopenharmony_ci AVCastPicker( 128e41f4b71Sopenharmony_ci { 129e41f4b71Sopenharmony_ci customPicker: (): void => this.ImageBuilder() // Add a custom parameter. 130e41f4b71Sopenharmony_ci } 131e41f4b71Sopenharmony_ci ).size({ height: 45, width:45 }) 132e41f4b71Sopenharmony_ci } 133e41f4b71Sopenharmony_ci } 134e41f4b71Sopenharmony_ci } 135e41f4b71Sopenharmony_ci 136e41f4b71Sopenharmony_ci // Custom content 137e41f4b71Sopenharmony_ci @Builder 138e41f4b71Sopenharmony_ci ImageBuilder(): void { 139e41f4b71Sopenharmony_ci Image(this.pickerImage) 140e41f4b71Sopenharmony_ci .size({ width: '100%', height: '100%' }) 141e41f4b71Sopenharmony_ci .backgroundColor('#00000000') 142e41f4b71Sopenharmony_ci .fillColor(Color.Black) 143e41f4b71Sopenharmony_ci } 144e41f4b71Sopenharmony_ci ``` 145e41f4b71Sopenharmony_ci 146e41f4b71Sopenharmony_ci2. 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.) 147e41f4b71Sopenharmony_ci 148e41f4b71Sopenharmony_ci ```ts 149e41f4b71Sopenharmony_ci import { audio } from '@kit.AudioKit'; 150e41f4b71Sopenharmony_ci 151e41f4b71Sopenharmony_ci async observerDevices() { 152e41f4b71Sopenharmony_ci let audioManager = audio.getAudioManager(); 153e41f4b71Sopenharmony_ci let audioRoutingManager = audioManager.getRoutingManager(); 154e41f4b71Sopenharmony_ci 155e41f4b71Sopenharmony_ci // When the AVCastPicker component is started for the first time, obtain the current device and refresh the content displayed. 156e41f4b71Sopenharmony_ci this.changePickerShow(audioRoutingManager.getPreferredOutputDeviceForRendererInfoSync(this.audioRendererInfo)); 157e41f4b71Sopenharmony_ci 158e41f4b71Sopenharmony_ci // Listen for the switching of the audio output device and display different styles based on the device type. 159e41f4b71Sopenharmony_ci audioRoutingManager.on('preferOutputDeviceChangeForRendererInfo', this.audioRendererInfo, (desc: audio.AudioDeviceDescriptors) => { 160e41f4b71Sopenharmony_ci this.changePickerShow(audioRoutingManager.getPreferredOutputDeviceForRendererInfoSync(this.audioRendererInfo)); 161e41f4b71Sopenharmony_ci }); 162e41f4b71Sopenharmony_ci } 163e41f4b71Sopenharmony_ci 164e41f4b71Sopenharmony_ci // Refresh the custom resource pickerImage after the device is changed. 165e41f4b71Sopenharmony_ci private changePickerShow(desc: audio.AudioDeviceDescriptors) { 166e41f4b71Sopenharmony_ci if (desc[0].deviceType === 2) { 167e41f4b71Sopenharmony_ci this.pickerImage = $r('app.media.sound'); 168e41f4b71Sopenharmony_ci } else if (desc[0].deviceType === 7) { 169e41f4b71Sopenharmony_ci this.pickerImage = $r('app.media.bluetooth'); 170e41f4b71Sopenharmony_ci } else { 171e41f4b71Sopenharmony_ci this.pickerImage = $r('app.media.earpiece'); 172e41f4b71Sopenharmony_ci } 173e41f4b71Sopenharmony_ci } 174e41f4b71Sopenharmony_ci ``` 175