diff --git a/zh-cn/application-dev/media/Readme-CN.md b/zh-cn/application-dev/media/Readme-CN.md index 17a59c5d2d5df7b6bc1384d1423b01a275796023..9052923e4453c37acfbc23af656ff2b861945d22 100755 --- a/zh-cn/application-dev/media/Readme-CN.md +++ b/zh-cn/application-dev/media/Readme-CN.md @@ -49,7 +49,8 @@ - [分布式媒体会话概述](distributed-avsession-overview.md) - [使用分布式媒体会话](using-distributed-avsession.md) - 音视频投播 - - [使用音视频投播](using-avsession-avcast.md) + - [音视频投播概述](avcastpicker-overview.md) + - [使用音视频投播](using-avcastpicker.md) - 相机 - [相机开发概述](camera-overview.md) - 相机开发指导 diff --git a/zh-cn/application-dev/media/avcastpicker-overview.md b/zh-cn/application-dev/media/avcastpicker-overview.md new file mode 100644 index 0000000000000000000000000000000000000000..231312539fcfb854a5a47ab95fdbef6d80da02f7 --- /dev/null +++ b/zh-cn/application-dev/media/avcastpicker-overview.md @@ -0,0 +1,55 @@ +# 音视频投播概述 + +OpenHarmony提供了统一的应用内音视频投播功能设计,通过提供投播组件和标准的接口,帮助开发者可以简单高效地实现将音视频资源投放到其他设备播放,即实现跨端投播。 + +同时,系统提供默认投播协议Cast+,可以有效提升投播体验。 + +使用系统提供的投播组件和接口,应用只需要设置对应的资源信息、监听投播中的相关状态,以及应用主动控制的行为(如:播放、暂停)。其他动作包括图标切换、设备的发现、连接、认证等,均由系统完成。 + +## 基本概述 + +- **媒体会话(AVSession)** + + 音视频管控服务,用于对系统中所有音视频行为进行统一的管理。 + + 本地播放时,应用需要向媒体会话提供播放的媒体信息(如正在播放的歌曲、歌曲的播放状态等),并接收和相应播控中心发出的控制命令(如暂停、下一首等)。具体请参考[本地媒体会话](using-avsession-developer.md)。 + + 投播时,通过AVSession,应用可以投播能力的设置和查询,并创建投播控制器。 + +- **投播组件[AVCastPicker](../reference/arkui-ts/ohos-avcastpicker.md)** + + 系统级的投播组件,可嵌入应用界面的UI组件。当用户点击该组件后,系统将进行设备发现、连接、认证等流程,应用仅需要通过接口获取投播中相关的回调信息。 + +- **投播控制器[AVCastController](../reference/apis/js-apis-avsession.md#avcastcontroller10)** + + 在投播后,由应用发起的对远端播放控制的接口,包括播放、暂停、调节音量、设置播放模式、设置播放速度等能力。 + +- **后台长时任务** + + 应用实现后台播放,需申请后台长时任务,避免应用在投播后被系统后台清理或冻结。具体参考[长时任务开发指导](../task-management/continuous-task-dev-guide.md)。 + +## 分布式投播交互过程 + +![](figures/cast-interaction-diagram.png) + +1. 用户在应用界面上点击AVCastPicker组件,触发系统发现可用于投播的设备。用户在设备列表中选择对应设备后,系统连接对应设备。 +2. 应用通过AVSession监听设备的连接情况,监听到设备已连接后,创建一个AVCastController用于发送控制命令(如播放、暂停、下一首等)。 +3. 在本端(包括应用内和播控中心)控制播放时,控制命令将通过AVCastController发送,本端和远端基于Cast+的能力进行数据传输和信息同步。然后更新远端系统预置播放器的状态。 +4. 用户同样可以在远端直接控制播放,将直接修改远端播放器的状态。 +5. 当远端播放器状态变更后,将触发回调,将状态信息返回到本端。应用可以通过AVCastController监听到远端播放器状态变化。 + +## 接入说明 + +### 基本原则 + +应用需要接入AVSession,才可以使用系统提供的统一投播能力,由系统进行设备发现和管理。系统不额外提供音视频设备发现的接口给应用进行选择和切换设备。 + +使用系统提供的统一投播组件,应用无需关注设备的发现连接过程,仅需关注设备在远端是否可用。当用户通过投播组件,选择了某个远端设备并连接成功,应用将通过回调获取到信息,然后可以创建一个AVCastController,用于控制远端设备的播放。 + +当进入到远端设备投播状态时,应用也可以对应用界面进行重新绘制,比如界面变更为一个遥控器,可控制远端播放。建议应用在进入远端投播时,停止本地的播放器,避免本端和远端设备同时播放的情况,提升用户体验。 + +### 音视频投播与分布式媒体会话的关联与差异 + +1. 分布式会话是基于分布式软总线的能力在双端设备之间进行会话信息的同步;投播能力基于Cast+的能力进行数据传输和信息同步,支持的设备类型更丰富。 +2. 分布式会话投播音频,需要由用户先进行双端设备的连接;投播成功后,应用在本端设备的控制和本地播放类似,而投播能力支持在远端设备进行播放的展示,体验上会更有优势。 +3. 分布式会话仅支持音频投播,不支持视频投播;投播能力后续会扩展,将支持视频投播。 \ No newline at end of file diff --git a/zh-cn/application-dev/media/figures/cast-interaction-diagram.png b/zh-cn/application-dev/media/figures/cast-interaction-diagram.png new file mode 100644 index 0000000000000000000000000000000000000000..e69fcab98731e81a7e6092832852aebe6bb4908c Binary files /dev/null and b/zh-cn/application-dev/media/figures/cast-interaction-diagram.png differ diff --git a/zh-cn/application-dev/media/using-avcastpicker.md b/zh-cn/application-dev/media/using-avcastpicker.md new file mode 100644 index 0000000000000000000000000000000000000000..f8731b4e65b15ddcde0812437e35b3a346d36485 --- /dev/null +++ b/zh-cn/application-dev/media/using-avcastpicker.md @@ -0,0 +1,237 @@ +# 使用音视频投播 + +通过本开发指导,完成一次音频跨设备投播。 + +## 接口说明 + +对于每个异步调用的API均提供了callback函数和Promise函数,以下示例均采用callback函数。详细的API接口说明,请参考[AVCastPicker组件参考](../reference/arkui-ts/ohos-avcastpicker.md)和[AVCastController API参考文档](../reference/apis/js-apis-avsession.md#avcastcontroller10)。 + +| 接口 | 说明 | +| -------- | -------- | +| getAVCastController(callback: AsyncCallback\): void | 获取远端投播时的控制接口。| +| on(type: 'outputDeviceChange', callback: (state: ConnectionState, device: OutputDeviceInfo) => void): void | 注册设备变化的回调,同时包含了设备的连接状态。| +| sendControlCommand(command: AVCastControlCommand, callback: AsyncCallback\): void | 投播会话的控制接口,用于进行投播中的各种播控指令 | +| prepare(item: AVQueueItem, callback: AsyncCallback\): void | 准备播放,进行资源加载和缓冲,不会触发真正的播放 | +| start(item: AVQueueItem, callback: AsyncCallback\): void | 开始播放媒体资源 | +| on(type: 'playbackStateChange', filter: Array\ \| 'all', callback: (state: AVPlaybackState) => void) | 注册播放状态变化的回调 | +| on(type: 'mediaItemChange', callback: AsyncCallback\): void | 注册当前播放内容更新的回调,返回当前播放的内容的信息。| + +>**说明:** +> +> AVCastController由系统获取并返回,在设备连接成功后获取,在设备断开后不能继续使用,否则会抛出异常。 + +## 开发步骤 + +1. 创建播放器,并创建AVSession。 + + 通过AVSessionManager创建并激活媒体会话。 + + ```ts + import AVSessionManager from '@ohos.multimedia.avsession'; //导入AVSession模块 + + // 创建session + async createSession() { + let session: AVSessionManager.AVSession = await AVSessionManager.createAVSession(this.context, 'SESSION_NAME', 'audio'); + session.activate(); + console.info(`session create done : sessionId : ${session.sessionId}`); + } + ``` + +2. 在需要投播的播放界面创建投播组件AVCastPicker。 + + ```ts + // 创建组件,并设置大小 + build() { + Row() { + Column() { + AVCastPicker() + .width('40vp') + .height('40vp') + .border({ width: 1, color: Color.Red }) + } + } + } + ``` + +3. 设置AVSession的信息,注册AVSession的回调。用于感知投播连接。 + + ```ts + async setListenerFromController() { + let session: AVSessionManager.AVSession = ALLREADY_CREATE_A_SESSION; + + // 对于应用来说,可以在每次更新资源的时候,设置设备过滤器,以通知系统进行设备选择界面的呈现 + // 如果应用不需要,或者不设置,系统会按照默认的设备策略进行展示 + // 设备过滤,一般是由应用根据播放的资源指定能够支持的投播设备 + // 通过extras 的 deviceFilter 设置设备过滤条件 + let extras = { + deviceFilter: AVCastDeviceCategory.DEVICE_CAPABILITY_CAST_STREAM; + } + await session.setExtras(extras).then(() => { + console.info(`Set extras successfully`); + }).catch((err) => { + console.error(`Failed to set extras. Code: ${err.code}, message: ${err.message}`); + }) + + // 监听设备连接状态的变化 + session.on("outputDeviceChange", (state, device) => { + if (state == AVCastState.STATE_CONNECTED) { // 设备连接成功 + global.avcastcontroller = avsession.getAVCastController(); + console.info('get a cast controller successfully'); + console.info(`device connected ` + ${JSON.stringify(device)}); + + // 设置播放参数,开始播放 + var playItem = { + itemId: 0, + description: { + mediaId: '12345', + mediaName: 'song1', + mediaType: 'AUDIO', + mediaUri: 'http://resource1_address', + mediaSize: 12345, + startPosition: 0, + duration: 0, + artist: 'mysong', + albumTitle: 'song1_title', + albumCoverUri: "http://resource1_album_address", + lyricUri: "http://resource1_lyric_address", + iconUri: "http://resource1_icon_address", + appName: 'MyMusic' + } + }; + // 准备播放,这个不会触发真正的播放,会进行加载和缓冲 + global.avcastcontroller.prepare(playItem, () => { + console.info('prepare done'); + }); + // 启动播放 + global.avcastcontroller.start(playItem, () => { + console.info('play done'); + }); + + // 列表里的第一首歌曲投播的时候,本端的Player要停止 + this.localplayer.stop(); + + // 本端投播后的应用界面由应用进行专辑图、歌手等信息的刷新 + + // 远端状态的回调,这个回调需要应用进行界面刷新,而不需要执行控制操作 + // 回调包括播放状态,播放位置,播放速度,播放模式等 + global.avcontroller.on('playbackStateChange', filter: 'all', (state) => { + console.info('playbackStateChange ' + state); + }); + // 用于响应远端进行上一首、下一首 + global.avcontroller.on('playNext', () => { + // 应用根据列表顺序,更新新的资源进行播放 + var nextPlayItem = { + itemId: 2, + description: { + mediaId: '12345', + mediaName: 'song2', + mediaType: 'AUDIO', + mediaUri: 'http://resource2_address', + mediaSize: 12345, + startPosition: 0, + duration: 0, + artist: 'mysong', + albumTitle: 'song2_title', + albumCoverUri: "http://resource2_album_address", + lyricUri: "http://resource2_lyric_address", + iconUri: "http://resource2_icon_address", + appName: 'MyMusic' + } + }; + // 准备播放 + global.avcastcontroller.prepare(nextPlayItem, () => { + console.info('prepare done'); + }); + // 启动播放 + global.avcastcontroller.start(nextPlayItem, () => { + console.info('play done'); + }); + }); + } + } + + // 可以通过getOutputDevice接口主动查询连接的设备 + session.getOutputDevice((device) => { + console.info(`current routing device` + ${JSON.stringify(device)}); + }); + } + ``` + +4. 通过AVSession获取投播控制器AVCastController,用于控制应用内的播放。 + + ```ts + async sendCommandToSessionByController() { + // 记录从avsession获取的远端控制器 + // 下发播放命令 + let avCommand: AVSessionManager.AVCastControlCommand = {command:'play'}; + global.avcontroller.sendControlCommand(avCommand); + + // 下发暂停命令 + let avCommand: AVSessionManager.AVCastControlCommand = {command:'pause'}; + global.avcontroller.sendControlCommand(avCommand); + + // 播放、暂停等的操作,可以通过状态的回调接口获取到,然后进行本端界面的刷新 + } + ``` + +5. 申请投播长时任务,避免应用在投播进入后台时被系统冻结,导致无法持续投播。 + + ```ts + import backgroundTaskManager from '@ohos.resourceschedule.backgroundTaskManager'; + import wantAgent from '@ohos.app.ability.wantAgent'; + + function startContinuousTask() { + let wantAgentInfo = { + // 点击通知后,将要执行的动作列表 + wants: [ + { + bundleName: "com.example.myapplication", + abilityName: "EntryAbility", + } + ], + // 点击通知后,动作类型 + operationType: wantAgent.OperationType.START_ABILITY, + // 使用者自定义的一个私有值 + requestCode: 0, + // 点击通知后,动作执行属性 + wantAgentFlags: [wantAgent.WantAgentFlags.UPDATE_PRESENT_FLAG] + }; + + // 通过wantAgent模块的getWantAgent方法获取WantAgent对象 + try { + wantAgent.getWantAgent(wantAgentInfo).then((wantAgentObj) => { + try { + backgroundTaskManager.startBackgroundRunning(mContext, + backgroundTaskManager.BackgroundMode.MULTI_DEVICE_CONNECTION, wantAgentObj).then(() => { + console.info("Operation succeeded"); + }).catch((error) => { + console.error(`Operation failed. code is ${error.code} message is ${error.message}`); + }); + } catch (error) { + console.error(`Operation failed. code is ${error.code} message is ${error.message}`); + } + }); + } catch (error) { + console.error(`Operation getWantAgent failed. code is ${error.code} message is ${error.message}`); + } + } + ``` + +6. 音频焦点的处理。请参考[多音频并发处理](audio-playback-concurrency.md)。 + + 在应用进入投播后,当前应用需要去注册焦点处理,以免被其他应用的焦点申请而影响。 + + **当前投播支持全局切换,后续如果规格变更,再同步调整方案说明。** + +7. 结束投播。 + + 当远端设备断开的时候,应用会收到事件,系统会自动断开连接。 + + 应用也可以使用断开投播的接口,主动进行投播连接的断开。 + + ```ts + async release() { + // 一般来说,应用退出时,而不希望继续投播,可以主动结束 + await global.avsession.stopCast(); + } + ``` diff --git a/zh-cn/application-dev/media/using-avsession-avcast.md b/zh-cn/application-dev/media/using-avsession-avcast.md deleted file mode 100644 index 2d33da6d87b0296708546d31087649a289457633..0000000000000000000000000000000000000000 --- a/zh-cn/application-dev/media/using-avsession-avcast.md +++ /dev/null @@ -1,307 +0,0 @@ -# 音视频投播开发 - -鸿蒙提供了统一的应用内音视频投播功能设计,通过提供投播组件和标准的接口,使得应用进行跨端投播音视频资源变得简单便捷。同时,系统默认支持Cast+协议,有效提升了投播体验。使用系统提供的投播组件和接口后,应用仅需要负责进行资源信息的设置,投播中部分状态的监听,以及应用主动控制的行为,如播放、暂停、切换资源等,其他动作包括图标切换,设备的发现、连接、认证等,都由系统统一负责完成。 - - -## 基本概念 - -- 媒体会话(AVSession):本地播放时用于进行媒体播放中的信息的更新和对系统播控中心的控制响应,[媒体会话提供方接入参考](using-avsession-developer.md)。 在投播时,AVSession用于在本地播放和投播之间切换的“枢纽”接口,把二者联系起来,即在本地播放时,如果接收到远端设备的连接状态,则应用感知到远端投播场景,进入到远端投播状态。通过AVSession可以进行应用投播能力的设置和查询,并进行投播控制器的创建。 -- 投播组件[AVCastPicker](../reference/apis/js-apis-avcastpicker.md):应用用于创建系统级的投播组件,嵌入在应用内界面,当用户点击后,由系统负责进行设备发现、连接、认证,应用只需要通过接口获取到投播中的状态回调。 -- 投播控制器[AVCastController](../reference/apis/js-apis-avsession.md):在投播后,由应用发起的对远端播放控制的接口,包括播放、暂停、调节音量、设置播放模式、设置播放速度等能力。 -- 后台长时任务:进行投播时应用后台任务的申请,避免应用在投播后被系统后台清理或冻结。后台长时任务[开发参考](../task-management/continuous-task-dev-guide.md)。 - -## 接入说明 - -- 基本原则 - -应用需要接入AVSession才可以使用系统提供的统一投播能力。系统不额外提供音视频设备发现的接口由应用选择和切换,需要通过系统提供的接口进行音视频的投播接入。 - -- 详细说明 - -鸿蒙系统把本地播控和远端投播融合归一到AVSession中,体现了系统的统一设计。使用系统提供的统一投播组件,应用可以减少对设备发现连接的关注,而只需要关注连接设备是否在远端进行。当用户通过投播组件,选择了某个远端设备并连接成功,应用会通过回调接口获取到该设备连接成功的事件,然后可以创建一个“远端遥控器” AVCastController,从而实现对远端设备播放的控制操作。当进入到远端设备投播状态时,应用也可以对应用界面进行重新绘制,比如呈现遥控器状态。一个比较好的体验是,在进入远端投播时,本地的播放器最好停止,以防止本端和投播端设备同时播放的情形。 - -对于本端和远端设备的场景的区分,参考 AVCastCategory 的定义: - -```ts -/** - * The default cast type "local", media can be routed on the same device, - * including internal speakers or audio jacks on the device itself, A2DP devices. - */ -CATEGORY_LOCAL = 0, - -/** - * The remote category indicating the media is presenting on a different device - * the application need get an AVCastController to control remote playback. - */ -CATEGORY_REMOTE = 1, -``` - -本次的投播能力和已有的分布式会话有什么关联和区别? - -1. 分布式会话是基于分布式软总线的能力在双端设备之间进行会话信息的同步,投播能力基于Cast+的能力进行数据传输和信息同步,支持的设备类型更丰富; -2. 分布式会话投播音频投播成功后,远端无对应信息展示,仅有声音会传输到对端设备;而投播能力支持在远端设备进行播放的展示,体验上会更有优势; -2. 投播能力当前支持音频,长期会支持视频,这个是分布式会话不支持的; -3. 分布式会话能力长期会融入到投播能力中,由系统提供统一的接口包装,更容易接入和使用。 - -## 接口说明 - -接口返回值有两种返回形式:callback和promise,下表中为callback形式接口,promise和callback只是返回值方式不一样,功能相同。 - -### 投播组件接口 - -更多API说明请参见[API文档](../reference/apis/js-apis-avcastpicker.md)。 - -| 接口 | 说明 | -| -------- | -------- | -| AVCastPicker |投播组件的定义 | - -### 投播相关的主要接口 - -更多API说明请参见[API文档](../reference/apis/js-apis-avsession.md)。 - -| 接口定义 | 说明 | -| -------- | -------- | -| getAVCastController(callback: AsyncCallback\): void; | 获取远端投播时的控制接口。| -| on(type: 'outputDeviceChange', callback: (state: ConnectionState, device: OutputDeviceInfo) => void): void; | 注册设备变化的回调,同时包含了设备的连接状态。| -| sendControlCommand(command: AVCastControlCommand, callback: AsyncCallback\): void; | 投播会话的控制接口,用于进行投播中的各种播控指令 | -| prepare(item: AVQueueItem, callback: AsyncCallback): void | 准备播放,进行资源加载和缓冲,不会触发真正的播放 | -| start(item: AVQueueItem, callback: AsyncCallback): void | 开始播放媒体资源 | -| on(type: 'playbackStateChange', filter: Array\ \| 'all', callback: (state: AVPlaybackState) => void) | 注册播放状态变化的回调 | -| on(type: 'mediaItemChange', callback: AsyncCallback\): void; | 注册当前播放内容更新的回调,返回当前播放的内容的信息。| - -Note: - -*AVCastController由系统获取并返回,在设备连接成功后获取,在设备断开后不能继续使用,否则会抛出异常* - - -## 应用开发步骤 - -应用接入投播功能,分为如下几步: - -1. 创建AVSession,既可以用于本地,也用于投播的实现 -2. 在需要投播的播放界面绘制投播组件 -3. 向AVSession注册设备投播过程状态的回调,感知投播连接 -4. 通过AVSession获取投播控制器,进行投播中的播放控制 -5. 投播启动后,应用需要进行长时任务的申请 -6. 投播结束后,销毁过程对象 - -### 接入效果展示 - -![Cast Demo](figures/cast-demo.png) - -### 应用接入示意 - -![Cast Interaction Diagram](figures/cast-interaction-diagram.png) - -### 进入投播和远端控制响应 - -1. 创建播放器,并创建AVSession,通过AVSessionManager的方法创建并激活媒体会话。 - -```ts -import AVSessionManager from '@ohos.multimedia.avsession'; //导入AVSession模块 - -// 创建session -async createSession() { - let session: AVSessionManager.AVSession = await AVSessionManager.createAVSession(this.context, 'SESSION_NAME', 'audio'); - session.activate(); - console.info(`session create done : sessionId : ${session.sessionId}`); -} -``` - -2. 在播放页面创建投播组件。 - -```ts -// 创建组件,并设置大小 -build() { - Row() { - Column() { - AVCastPicker() - .width('40vp') - .height('40vp') - .border({ width: 1, color: Color.Red }) - } - } -} -``` - -3. 设置AVSession的信息,注册AVSession的回调: - -```ts -async setListenerFromController() { - let session: AVSessionManager.AVSession = ALLREADY_CREATE_A_SESSION; - - // 对于应用来说,可以在每次更新资源的时候,设置设备过滤器,以通知系统进行设备选择界面的呈现 - // 如果应用不需要,或者不设置,系统会按照默认的设备策略进行展示 - // 设备过滤,一般是由应用根据播放的资源指定能够支持的投播设备 - // 通过extras 的 deviceFilter 设置设备过滤条件 - let extras = { - deviceFilter: AVCastDeviceCategory.DEVICE_CAPABILITY_CAST_STREAM; - } - await session.setExtras(extras).then(() => { - console.info(`Set extras successfully`); - }).catch((err) => { - console.error(`Failed to set extras. Code: ${err.code}, message: ${err.message}`); - }) - - // 监听设备连接状态的变化 - session.on("outputDeviceChange", (state, device) => { - if (state == AVCastState.STATE_CONNECTED) { // 设备连接成功 - global.avcastcontroller = avsession.getAVCastController(); - console.info('get a cast controller successfully'); - console.info(`device connected ` + ${JSON.stringify(device)}); - - // 设置播放参数,开始播放 - var playItem = { - itemId: 0, - description: { - mediaId: '12345', - mediaName: 'song1', - mediaType: 'AUDIO', - mediaUri: 'http://resource1_address', - mediaSize: 12345, - startPosition: 0, - duration: 0, - artist: 'mysong', - albumTitle: 'song1_title', - albumCoverUri: "http://resource1_album_address", - lyricUri: "http://resource1_lyric_address", - iconUri: "http://resource1_icon_address", - appName: 'MyMusic' - } - }; - // 准备播放,这个不会触发真正的播放,会进行加载和缓冲 - global.avcastcontroller.prepare(playItem, () => { - console.info('prepare done'); - }); - // 启动播放 - global.avcastcontroller.start(playItem, () => { - console.info('play done'); - }); - - // 列表里的第一首歌曲投播的时候,本端的Player要停止 - this.localplayer.stop(); - - // 本端投播后的应用界面由应用进行专辑图、歌手等信息的刷新 - - // 远端状态的回调,这个回调需要应用进行界面刷新,而不需要执行控制操作 - // 回调包括播放状态,播放位置,播放速度,播放模式等 - global.avcontroller.on('playbackStateChange', filter: 'all', (state) => { - console.info('playbackStateChange ' + state); - }); - // 用于响应远端进行上一首、下一首 - global.avcontroller.on('playNext', () => { - // 应用根据列表顺序,更新新的资源进行播放 - var nextPlayItem = { - itemId: 2, - description: { - mediaId: '12345', - mediaName: 'song2', - mediaType: 'AUDIO', - mediaUri: 'http://resource2_address', - mediaSize: 12345, - startPosition: 0, - duration: 0, - artist: 'mysong', - albumTitle: 'song2_title', - albumCoverUri: "http://resource2_album_address", - lyricUri: "http://resource2_lyric_address", - iconUri: "http://resource2_icon_address", - appName: 'MyMusic' - } - }; - // 准备播放 - global.avcastcontroller.prepare(nextPlayItem, () => { - console.info('prepare done'); - }); - // 启动播放 - global.avcastcontroller.start(nextPlayItem, () => { - console.info('play done'); - }); - }); - } - } - - // 可以通过getOutputDevice接口主动查询连接的设备 - session.getOutputDevice((device) => { - console.info(`current routing device` + ${JSON.stringify(device)}); - }); -} -``` - -4. 使用AVCastController进行应用内的播放控制: - -```ts -async sendCommandToSessionByController() { - // 记录从avsession获取的远端控制器 - // 下发播放命令 - let avCommand: AVSessionManager.AVCastControlCommand = {command:'play'}; - global.avcontroller.sendControlCommand(avCommand); - - // 下发暂停命令 - let avCommand: AVSessionManager.AVCastControlCommand = {command:'pause'}; - global.avcontroller.sendControlCommand(avCommand); - - // 播放、暂停等的操作,可以通过状态的回调接口获取到,然后进行本端界面的刷新 -} -``` - -5. 申请投播长时任务,避免应用在投播进入后台时被系统冻结,导致无法持续投播 - -```ts -import backgroundTaskManager from '@ohos.resourceschedule.backgroundTaskManager'; -import wantAgent from '@ohos.app.ability.wantAgent'; - -function startContinuousTask() { - let wantAgentInfo = { - // 点击通知后,将要执行的动作列表 - wants: [ - { - bundleName: "com.example.myapplication", - abilityName: "EntryAbility", - } - ], - // 点击通知后,动作类型 - operationType: wantAgent.OperationType.START_ABILITY, - // 使用者自定义的一个私有值 - requestCode: 0, - // 点击通知后,动作执行属性 - wantAgentFlags: [wantAgent.WantAgentFlags.UPDATE_PRESENT_FLAG] - }; - - // 通过wantAgent模块的getWantAgent方法获取WantAgent对象 - try { - wantAgent.getWantAgent(wantAgentInfo).then((wantAgentObj) => { - try { - backgroundTaskManager.startBackgroundRunning(mContext, - backgroundTaskManager.BackgroundMode.MULTI_DEVICE_CONNECTION, wantAgentObj).then(() => { - console.info("Operation succeeded"); - }).catch((error) => { - console.error(`Operation failed. code is ${error.code} message is ${error.message}`); - }); - } catch (error) { - console.error(`Operation failed. code is ${error.code} message is ${error.message}`); - } - }); - } catch (error) { - console.error(`Operation getWantAgent failed. code is ${error.code} message is ${error.message}`); - } -} -``` - -6. 音频焦点的处理 - -在应用进入投播后,当前应用需要去注册焦点处理,以免被其他应用的焦点申请而影响。 -**当前投播支持全局切换,后续如果规格变更,再同步调整方案说明** - -7. 结束投播 - -当远端设备断开的时候,应用会收到事件,系统会自动断开连接。 - -应用也可以使用断开投播的接口,主动进行投播连接的断开。 - -```ts -async release() { - // 一般来说,应用退出时,而不希望继续投播,可以主动结束 - await global.avsession.stopCast(); -} -``` \ No newline at end of file diff --git a/zh-cn/application-dev/reference/apis/js-apis-avcastpicker.md b/zh-cn/application-dev/reference/apis/js-apis-avcastpicker.md deleted file mode 100644 index 8b8402a2c8685da109ba06c1a90e6b4f31b5d1d3..0000000000000000000000000000000000000000 --- a/zh-cn/application-dev/reference/apis/js-apis-avcastpicker.md +++ /dev/null @@ -1,37 +0,0 @@ -# @ohos.avcastpicker (AVCastPicker) - -本模块提供创建投播组件的功能,提供了设备发现连接的统一入口。 - -> **说明:** -> -> 本模块首批接口从API version 10开始支持。后续版本的新增接口,采用上角标单独标记接口的起始版本。 -> -> 示例效果请以真机运行为准,当前IDE预览器不支持。 - -## 导入模块 - -```js -import { AVCastPicker} from '@ohos.avcastpicker'; -``` - -**系统能力:** SystemCapability.Multimedia.AVSession - -**示例:** -```ts -import { AVCastPicker } from '@ohos.avcastpicker' - -@Entry -@Component -struct Index { - build() { - Row() { - Column() { - AVCastPicker() - .width('40vp') - .height('40vp') - .border({ width: 1, color: Color.Red }) - }.height('50%') - }.width('50%') - } -} -``` diff --git a/zh-cn/application-dev/reference/arkui-ts/Readme-CN.md b/zh-cn/application-dev/reference/arkui-ts/Readme-CN.md index f0170225f5477a10ef542eb4ba8f48af423c1fac..7607178d5492a190f51dbc5c29e6129b2081227b 100644 --- a/zh-cn/application-dev/reference/arkui-ts/Readme-CN.md +++ b/zh-cn/application-dev/reference/arkui-ts/Readme-CN.md @@ -156,6 +156,8 @@ - [OffscreenCanvas](ts-components-offscreencanvas.md) - [OffscreenCanvasRenderingContext2D对象](ts-offscreencanvasrenderingcontext2d.md) - [Path2D对象](ts-components-canvas-path2d.md) +- 高级组件 + - [@ohos.avcastpicker (投播组件)](ohos-avcastpicker.md) - 动画 - [属性动画](ts-animatorproperty.md) - [显式动画](ts-explicit-animation.md) diff --git a/zh-cn/application-dev/reference/arkui-ts/ohos-avcastpicker.md b/zh-cn/application-dev/reference/arkui-ts/ohos-avcastpicker.md new file mode 100644 index 0000000000000000000000000000000000000000..557059562df7d047434f293007ae49b90cbc9474 --- /dev/null +++ b/zh-cn/application-dev/reference/arkui-ts/ohos-avcastpicker.md @@ -0,0 +1,55 @@ +# @ohos.avcastpicker (投播组件) + +本模块提供创建投播组件AVCastPicker的功能,提供设备发现连接的统一入口。 + +> **说明:** +> +> - 本模块首批接口从API version 10开始支持。后续版本的新增接口,采用上角标单独标记接口的起始版本。 +> - 示例效果请以真机为准,当前不支持使用IDE预览器。 + +## 导入模块 + +```js +import { AVCastPicker} from '@ohos.avcastpicker'; +``` + +## 接口 + +AVCastPicker() + +投播组件,可用于将音视频资源投放到其它设备播放。 + +该组件为自定义组件,开发者在使用前需要先了解[@component](../../quick-start/arkts-create-custom-components.md)。 + +**系统能力:** SystemCapability.Multimedia.AVSession + +## 属性 + +支持[通用属性](ts-universal-attributes-size.md)。 + +## 事件 + +支持[通用事件](ts-universal-events-click.md)。 + +## 示例 + +投播功能的示例说明请参考[音视频投播](avcastpicker-overview.md)。 + +```ts +import { AVCastPicker } from '@ohos.avcastpicker' + +@Entry +@Component +struct Index { + build() { + Row() { + Column() { + AVCastPicker() + .width('40vp') + .height('40vp') + .border({ width: 1, color: Color.Red }) + }.height('50%') + }.width('50%') + } +} +```