1# 使用通话设备切换组件 2 3## 基本概念 4 5系统不再提供音频输出设备切换的API,如果需要应用内切换音频输出设备,请实现AVCastPicker组件,相关参数可参考[@ohos.multimedia.avCastPicker](../../reference/apis-avsession-kit/ohos-multimedia-avcastpicker.md) 和 [@ohos.multimedia.avCastPickerParam](../../reference/apis-avsession-kit/js-apis-avCastPickerParam.md)。 6 7本文将主要介绍AVCastPicker组件接入,实现通话设备切换。 8 9当前系统支持两种组件样式的显示方式:默认样式显示和自定义样式显示。如果应用选择显示默认样式,当设备切换时,系统将根据当前选择的设备显示系统默认的组件样式;如果应用选择显示自定义样式,那么需要应用根据设备的变化刷新自己定义的样式。 10 11## 开发步骤 12 13### 默认样式实现 14 151. 创建voice_call类型的AVSession,AVSession在构造方法中支持不同的类型参数,由AVSessionType定义,voice_call表示通话类型,如果不创建,将显示空列表。 16 17 ```ts 18 import { avSession } from '@kit.AVSessionKit'; 19 20 private session: avSession.AVSession | undefined = undefined; 21 22 // 通话开始时创建voice_call类型的avsession 23 this.session = await avSession.createAVSession(getContext(this), 'voiptest', 'voice_call'); 24 ``` 25 262. 在需要切换设备的通话界面创建AVCastPicker组件。 27 28 ```ts 29 import { AVCastPicker } from '@kit.AVSessionKit'; 30 31 // 创建组件,并设置大小 32 build() { 33 Row() { 34 Column() { 35 AVCastPicker() 36 .size({ height:45, width:45 }) 37 } 38 } 39 } 40 ``` 41 423. 创建VOICE_COMMUNICATION类型的AudioRenderer,并开始播放。具体通话音频播放等实现,请参考[AudioKit开发音频通话功能](../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 // 请按照实际场景设置,当前参数仅参考 51 samplingRate: audio.AudioSamplingRate.SAMPLE_RATE_48000, // 采样率 52 channels: audio.AudioChannel.CHANNEL_2, // 通道 53 sampleFormat: audio.AudioSampleFormat.SAMPLE_FORMAT_S16LE, // 采样格式 54 encodingType: audio.AudioEncodingType.ENCODING_TYPE_RAW // 编码格式 55 } 56 private audioRendererInfo: audio.AudioRendererInfo = { 57 // 需使用通话场景相应的参数 58 usage: audio.StreamUsage.STREAM_USAGE_VIDEO_COMMUNICATION, // 音频流使用类型:VOIP视频通话,默认为扬声器 59 rendererFlags: 0 // 音频渲染器标志:默认为0即可 60 } 61 private audioRendererOptions: audio.AudioRendererOptions = { 62 streamInfo: this.audioStreamInfo, 63 rendererInfo: this.audioRendererInfo 64 } 65 66 // 初始化,创建通话audiorenderer实例,设置监听事件 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. (可选)如果应用想知道设备切换情况,可以监听当前发声设备切换回调。 83 84 ```ts 85 import { audio } from '@kit.AudioKit'; 86 87 let audioManager = audio.getAudioManager(); // 先创建audiomanager 88 let audioRoutingManager = audioManager.getRoutingManager(); // 再调用AudioManager的方法创建AudioRoutingManager实例 89 90 // 可选监听当前发声设备切换回调 91 audioRoutingManager.on('preferOutputDeviceChangeForRendererInfo', this.audioRendererInfo, (desc: audio.AudioDeviceDescriptors) => { 92 console.info(`device change To : ${desc[0].deviceType}`); // 设备类型 93 }); 94 ``` 95 965. 通话结束后,销毁会话。 97 98 ```ts 99 // 通话结束销毁第一步创建的session 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### 自定义样式实现 110 111自定义样式通过设置[CustomBuilder](../../reference/apis-avsession-kit/ohos-multimedia-avcastpicker.md)类型的参数customPicker实现。 112 113实现自定义样式的步骤与实现默认样式基本相同,开发者可参考[默认样式实现](#默认样式实现),完成创建AVSession、实现音频播放等步骤。 114 115存在差异的步骤如下所示。 116 1171. 创建自定义AVCastPicker,需要新增自定义参数。(对应默认样式实现步骤2) 118 119 ```ts 120 import { AVCastPicker } from '@kit.AVSessionKit'; 121 122 @State pickerImage:ResourceStr = $r('app.media.earpiece'); // 自定义资源 123 124 build() { 125 Row() { 126 Column() { 127 AVCastPicker( 128 { 129 customPicker: (): void => this.ImageBuilder() // 新增自定义参数 130 } 131 ).size({ height: 45, width:45 }) 132 } 133 } 134 } 135 136 // 自定义内容 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. 如果应用要根据出声设备变化而改变自定义样式,必须监听设备切换,然后实时刷新自定义样式。(对应默认样式实现步骤4) 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 // 初次拉起AVCastPicker时需获取当前设备,刷新显示 156 this.changePickerShow(audioRoutingManager.getPreferredOutputDeviceForRendererInfoSync(this.audioRendererInfo)); 157 158 // 监听当前发声设备切换,及时根据不同设备类型显示不同的样式 159 audioRoutingManager.on('preferOutputDeviceChangeForRendererInfo', this.audioRendererInfo, (desc: audio.AudioDeviceDescriptors) => { 160 this.changePickerShow(audioRoutingManager.getPreferredOutputDeviceForRendererInfoSync(this.audioRendererInfo)); 161 }); 162 } 163 164 // 设备更新后刷新自定义资源pickerImage 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-->