• Home
Name Date Size #Lines LOC

..--

AppScope/06-May-2025-3532

entry/06-May-2025-1,1481,034

hvigor/06-May-2025-3533

screenshots/device/06-May-2025-

.gitignoreD06-May-2025119 1111

README.mdD06-May-20257.7 KiB220161

build-profile.json5D06-May-20251 KiB4342

hvigorfile.tsD06-May-2025341 85

hvigorwD06-May-20252.1 KiB6328

hvigorw.batD06-May-20252.1 KiB7859

oh-package-lock.json5D06-May-20251 KiB2827

oh-package.json5D06-May-2025838 2927

README.md

1# 通话设备切换
2
3### 介绍
4
5本示例主要展示了通话设备切换的相关功能,使用[@ohos.multimedia.avCastPicker](https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/reference/apis-avsession-kit/ohos-multimedia-avcastpicker.md)和[@ohos.multimedia.avCastPickerParam](https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/reference/apis-avsession-kit/js-apis-avCastPickerParam.md)等接口实现通话设备切换功能。
6
7> 注意:
8> 通话设备切换按钮可显示默认样式或者自定义样式,默认样式由系统提供,自定义组件由应用提供。还可参考相关的[开发指南](https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/media/avsession/using-switch-call-devices.md)9
10### 效果预览
11
12| 主页 | 默认样式页面 | 自定义样式页面 |
13|-------------------------------- | -------------------------------- | -------------------------------- |
14| ![Index](screenshots/device/Index.jpeg) | ![DefaultPicker](screenshots/device/DefaultPicker.jpeg) | ![CustomPicker](screenshots/device/CustomPicker.jpeg) |
15
16### 使用说明
17
181. 点击进入主页,可以选择点击按钮默认样式组件和自定义样式组件,如果点击默认样式组件,跳转到显示默认样式的页面;点击自定义样式组件,跳转到显示自定义样式的页面;
192. 进入页面后,有三个按钮,分别是start,stop和设备切换按钮,点击start按钮,可播放音频,点击stop,可暂停音频, 点击设备切换按钮,可选择当前输出设备并显示设备对应的样式。
20
21### 工程目录
22
23项目中关键的目录结构如下:
24
25```
26entry/src/main/ets/
27|---pages
28|---|---Index.ets                                  //初始界面实现
29|---|---DefaultPicker.ets                          //默认样式实现
30|---|---CustomPicker.ets                           //自定义样式实现
31
32```
33
34### 具体实现
35
36#### 初始界面实现
37
38  初始界面相关的实现都封装在pages/Index.ets下,源码参考:[pages/Index.ets](./entry/src/main/ets/pages/Index.ets)。
39
40  * 界面显示两个按钮分别为默认样式组件和自定义样式组件,可分别跳转到系统默认样式实现界面和自定义样式实现界面,相关代码如下:
41
42    ```ets
43    Button() {
44      // 按钮的内容
45    }
46    .onClick(async() => {
47      await router.pushUrl({ url:'pages/DefaultPicker' });//系统默认样式实现
48    })
49
50    Button() {
51      // 按钮的内容
52    }
53    .onClick(async() => {
54      await router.pushUrl({ url:'pages/CustomPicker' });//自定义样式实现
55    })
56    ```
57#### 默认系统样式
58
59  默认系统样式的相关内容封装在pages/DefaultPicker.ets下,源码参考:[pages/DefaultPicker.ets](./entry/src/main/ets/pages/DefaultPicker.ets)。
60
61  * 在需要切换设备的通话界面创建AVCastPicker组件。
62
63    ```ets
64    import { AVCastPicker } from '@kit.AVSessionKit';
65
66    AVCastPicker({
67      normalColor: this.avCastPickerColor,
68      activeColor: this.avCastPickerColor,
69    })
70      .size({ width: 45, height: 45 })
71    ```
72
73  * 拉起组件前需创建voice_call类型的AVSession,AVSession在构造方法中支持不同的类型参数,由AVSessionType定义,voice_call表示通话类型。
74
75    ```ets
76    import { avSession } from '@kit.AVSessionKit';
77
78    init() {
79      //...
80      this.session = await avSession.createAVSession(this.appContext, 'voiptest', 'voice_call');
81    }
82    ```
83
84  * 创建VOICE_COMMUNICATION类型的AudioRenderer,并播放,可模拟通话场景:
85
86    * 创建如下三个变量。
87
88    ```ets
89    private audioRendererInfo: audio.AudioRendererInfo = {
90      usage: audio.StreamUsage.STREAM_USAGE_VOICE_COMMUNICATION,
91      rendererFlags: 0
92    }
93    private audioStreamInfo: audio.AudioStreamInfo = {
94      samplingRate: audio.AudioSamplingRate.SAMPLE_RATE_48000, // 采样率
95      channels: audio.AudioChannel.CHANNEL_2, // 通道
96      sampleFormat: audio.AudioSampleFormat.SAMPLE_FORMAT_S16LE, // 采样格式
97      encodingType: audio.AudioEncodingType.ENCODING_TYPE_RAW // 编码格式
98    }
99    private  audioRendererOption: audio.AudioRendererOptions = {
100      streamInfo: this.audioStreamInfo,
101      rendererInfo: this.audioRendererInfo
102    }
103    ```
104
105    * 调用 startRenderer() 播放音频。
106
107    * 调用 stopRenderer() 暂停播放音频。
108
109#### 自定义样式
110
111  自定义样式的相关内容封装在pages/CustomPicker.ets下,源码参考:[pages/CustomPicker.ets](./entry/src/main/ets/pages/CustomPicker.ets)。
112
113  * 在需要切换设备的通话界面创建AVCastPicker组件。
114
115    ```ets
116
117    import { AVCastPicker } from '@kit.AVSessionKit';
118
119    @State pickerImage: ResourceStr = $r('app.media.ic_earpiece');
120
121    @Builder
122    ImangeBuilder(): void {
123      Image(this.pickerImage)
124        .size({ width: '100%', height: '100%' })
125        .backgroundColor('#00000000')
126        .fillColor(Color.Black)
127    }
128
129    Column() {
130      Button() {
131        AVCastPicker({
132          normalColor: this.avCastPickerColor,
133          activeColor: this.avCastPickerColor,
134          customPicker: (): void => this.ImangeBuilder(),
135          onStateChange: (state: AVCastPickerState) => {
136            console.error(`change avcastpicker: ${state}`);
137          }
138        })
139          .size({ width: 45, height: 45 })
140      }
141      .size({ width: 64, height: 64 })
142      .type(ButtonType.Circle)
143      .backgroundColor(Color.Orange)
144    }
145      .size({ width: '33%', height: 64 })
146
147    ```
148
149  * 拉起组件前也需创建voice_call类型的AVSession。为了保证能够正常更新样式,需要监听当前设备切换,如果当前设备切换,将刷新显示样式
150
151    ```ets
152
153    import { avSession } from '@kit.AVSessionKit';
154    import { audio } from '@kit.AudioKit';
155
156    init(){
157      this.session = await avSession.createAVSession(this.appContext, 'voiptest', 'voice_call');
158      this.observerDevices();
159    }
160
161    async observerDevices() {
162      if(!this.audioRoutingManager) {
163        return;
164      }
165      let desc: audio.AudioDeviceDescriptors = this.audioRoutingManager.getPreferredOutputDeviceForRendererInfoSync(this.audioRendererInfo);
166      this.changePickerShow(desc);
167      audioRoutingManager.on('preferOutputDeviceChangeForRendererInfo', this.audioRendererInfo, (desc: audio.AudioDeviceDescriptors) => {
168        if(!this.audioRoutingManager) {
169          return;
170        }
171        console.log(`device change to: ${desc[0].deviceType}`);
172        let devices: audio.AudioDeviceDescriptors = this.audioRoutingManager.getPreferredOutputDeviceForRendererInfoSync(this.audioRendererInfo);
173        this.changePickerShow(devices);
174      });
175    }
176
177    private changePickerShow(desc: audio.AudioDeviceDescriptors) {
178      if (desc[0].deviceType === 2) {
179        this.pickerImage = $r('app.media.ic_public_sound');
180      } else if (desc[0].deviceType === 7) {
181        this.pickerImage = $r('app.media.ic_bluetooth');
182      } else {
183        this.pickerImage = $r('app.media.ic_earpiece');
184      }
185    }
186
187    ```
188
189  * 创建VOICE_COMMUNICATION类型的AudioRenderer,并播放,可模拟通话场景,具体实现如默认样式。
190
191### 相关权限
192
193不涉及
194
195### 依赖
196
197不涉及
198
199### 约束与限制
200
2011. 本示例仅支持标准系统上运行。
202
2032. 本示例为Stage模型,支持API12版本SDK,SDK版本号(API Version 12 Release),镜像版本号(5.0 Release)。
204
2053. 本示例需要使用DevEco Studio 版本号(5.0 Release)及以上版本才可编译运行。
206
2074. 本示例手机设备支持,RK暂不支持。
208
209### 下载
210
211如需单独下载本工程,执行如下命令:
212
213```
214git init
215git config core.sparsecheckout true
216echo code/BasicFeature/Media/AVSession/AvCastPickerForCall > .git/info/sparse-checkout
217git remote add origin https://gitee.com/openharmony/applications_app_samples.git
218git pull origin master
219```
220