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