日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

HarmonyOS之深入解析媒体会话的管理

發(fā)布時(shí)間:2024/5/21 编程问答 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 HarmonyOS之深入解析媒体会话的管理 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

一、簡(jiǎn)介

  • AVSession 是一套媒體播放控制框架,對(duì)媒體服務(wù)和界面進(jìn)行解耦,并提供規(guī)范的通信接口,使應(yīng)用可以自由、高效地在不同的媒體之間完成切換。
  • 在使用完 AVSession 類后,需要及時(shí)進(jìn)行資源釋放。
  • 播放器類需要使用 ohos.media.player.Player,否則無(wú)法正常接收按鍵事件。

二、應(yīng)用場(chǎng)景

  • AVSession 框架有四個(gè)主要的類,控制著整個(gè)框架的核心,下圖簡(jiǎn)單的說(shuō)明四個(gè)核心媒體框架控制類的關(guān)系。

  • AVBrowser:
    • 媒體瀏覽器,通常在客戶端創(chuàng)建,成功連接媒體服務(wù)后,通過(guò)媒體控制器 AVController 向服務(wù)端發(fā)送播放控制指令。
    • 其主要流程為,調(diào)用 connect 方法向 AVBrowserService 發(fā)起連接請(qǐng)求,連接成功后在回調(diào)方法 AVConnectionCallback.onConnected 中發(fā)起訂閱數(shù)據(jù)請(qǐng)求,并在回調(diào)方法 AVSubscriptionCallback.onAVElementListLoaded 中保存請(qǐng)求的媒體播放數(shù)據(jù)。
    • 調(diào)用 AVBrowser的subscribeByParentMediaId(String, AVSubscriptionCallback) 之前,需要先執(zhí)行 unsubscribeByParentMediaId(String),防止重復(fù)訂閱。
  • AVController:
    • 媒體控制器,在客戶端 AVBrowser 連接服務(wù)成功后的回調(diào)方法 AVConnectionCallback.onConnected 中創(chuàng)建,用于向 Service 發(fā)送播放控制指令,并通過(guò)實(shí)現(xiàn) AVControllerCallback 回調(diào)來(lái)響應(yīng)服務(wù)端媒體狀態(tài)變化,例如曲目信息變更、播放狀態(tài)變更等,從而完成 UI 刷新。
  • AVBrowserService:
    • 媒體瀏覽器服務(wù),通常在服務(wù)端,通過(guò)媒體會(huì)話 AVSession 與媒體瀏覽器建立連接,并通過(guò)實(shí)現(xiàn) Player 進(jìn)行媒體播放。
    • AVBrowserService 有兩個(gè)重要的方法:
      • onGetRoot,處理從媒體瀏覽器 AVBrowser 發(fā)來(lái)的連接請(qǐng)求,通過(guò)返回一個(gè)有效的AVBrowserRoot對(duì)象表示連接成功;
      • onLoadAVElementList,處理從媒體瀏覽器 AVBrowser 發(fā)來(lái)的數(shù)據(jù)訂閱請(qǐng)求,通過(guò) AVBrowserResult.sendAVElementList(List) 方法返回媒體播放數(shù)據(jù)。使用 onLoadAVElementList(String, AVBrowserResult) 的 result 返回?cái)?shù)據(jù)前,需要執(zhí)行 detachForRetrieveAsync()。
  • AVSession:
    • 媒體會(huì)話,通常在 AVBrowserService 的 onStart 中創(chuàng)建,通過(guò) setAVToken 方法設(shè)置到 AVBrowserService 中,并通過(guò)實(shí)現(xiàn) AVSessionCallback 回調(diào)來(lái)接收和處理媒體控制器 AVController 發(fā)送的播放控制指令,如播放、暫停、跳轉(zhuǎn)至上一曲、跳轉(zhuǎn)至下一曲等。
  • AVElement:媒體元素,用于將播放列表從 AVBrowserService 傳遞給 AVBrowser。

三、API

① AVBrowser 的主要接口
接口名描述
AVBrowser(Context context, ElementName name, AVConnectionCallback callback, PacMap options)構(gòu)造AVBrowser實(shí)例,用于瀏覽AVBrowserService提供的媒體數(shù)據(jù)
connect()連接AVBrowserService
disconnect()與AVBrowserService斷開(kāi)連接
isConnected()判斷當(dāng)前是否已經(jīng)與AVBrowserService連接
getElementName()獲取AVBrowserService的ohos.bundle.ElementName實(shí)例
getRootMediaId()獲取默認(rèn)媒體id
getOptions()獲取AVBrowserService提供的附加數(shù)據(jù)
getAVToken()獲取媒體會(huì)話的令牌
getAVElement(String mediaId, AVElementCallback callback)輸入媒體的id,查詢對(duì)應(yīng)的ohos.media.common.sessioncore.AVElement信息,查詢結(jié)果會(huì)通過(guò)callback返回
subscribeByParentMediaId(String parentMediaId, AVSubscriptionCallback callback)查詢指定媒體id包含的所有媒體元素信息,并訂閱它的媒體信息更新通知
subscribeByParentMediaId(String parentMediaId, PacMap options, AVSubscriptionCallback callback)基于特定于服務(wù)的參數(shù)來(lái)查詢指定媒體id中的媒體元素的信息,并訂閱它的媒體信息更新通知
unsubscribeByParentMediaId(String parentMediaId)取消訂閱對(duì)應(yīng)媒體id的信息更新通知
unsubscribeByParentMediaId(String parentMediaId, AVSubscriptionCallback callback)取消訂閱與指定callback相關(guān)的媒體id的信息更新通知
② AVBrowserService 的主要接口
接口名描述
onGetRoot(String callerPackageName, int clientUid, PacMap options)回調(diào)方法,用于返回應(yīng)用程序的媒體內(nèi)容的根信息,在AVBrowser.connect()后進(jìn)行回調(diào)
onLoadAVElementList(String parentMediaId, AVBrowserResult result)回調(diào)方法,用于返回應(yīng)用程序的媒體內(nèi)容的結(jié)果信息AVBrowserResult,其中包含了子節(jié)點(diǎn)的AVElement列表,在AVBrowser的方法subscribeByParentMediaId或notifyAVElementListUpdated執(zhí)行后進(jìn)行回調(diào)
onLoadAVElement(String mediaId, AVBrowserResult result)回調(diào)方法,用于獲取特定的媒體項(xiàng)目AVElement結(jié)果信息,在AVBrowser.getAVElement方法執(zhí)行后進(jìn)行回調(diào)
getAVToken()獲取AVBrowser與AVBrowserService之間的會(huì)話令牌
setAVToken(AVToken token)設(shè)置AVBrowser與AVBrowserService之間的會(huì)話令牌
getBrowserOptions()獲取AVBrowser在連接AVBrowserService時(shí)設(shè)置的服務(wù)參數(shù)選項(xiàng)
getCallerUserInfo()獲取當(dāng)前發(fā)送請(qǐng)求的調(diào)用者信息
notifyAVElementListUpdated(String parentMediaId)通知所有已連接的AVBrowser當(dāng)前父節(jié)點(diǎn)的子節(jié)點(diǎn)已經(jīng)發(fā)生改變
notifyAVElementListUpdated(String parentId, PacMap options)通知所有已連接的AVBrowser當(dāng)前父節(jié)點(diǎn)的子節(jié)點(diǎn)已經(jīng)發(fā)生改變,可設(shè)置服務(wù)參數(shù)
③ AVController 的主要接口
接口名描述
AVController(Context context, AVToken avToken)構(gòu)造AVController實(shí)例,用于應(yīng)用程序與AVSession進(jìn)行交互以控制媒體播放
setControllerForAbility(Ability ability, AVController controller)將媒體控制器注冊(cè)到ability以接收按鍵事件
setAVControllerCallback(AVControllerCallback callback)注冊(cè)一個(gè)回調(diào)以接收來(lái)自AVSession的變更,例如元數(shù)據(jù)和播放狀態(tài)變更
releaseAVControllerCallback(AVControllerCallback callback)釋放與AVSession之間的回調(diào)實(shí)例
getAVQueueElement()獲取播放隊(duì)列
getAVQueueTitle()獲取播放隊(duì)列的標(biāo)題
getAVPlaybackState()獲取播放狀態(tài)
dispatchAVKeyEvent(KeyEvent keyEvent)應(yīng)用分發(fā)媒體按鍵事件給會(huì)話以控制播放
sendCustomCommand(String command, PacMap pacMap, GeneralReceiver receiverCb)應(yīng)用向AVSession發(fā)送自定義命令,參考o(jì)hos.media.common.sessioncore.AVSessionCallback.onCommand
getAVSessionAbility()獲取啟動(dòng)用戶界面的IntentAgent
getAVToken()獲取應(yīng)用連接到會(huì)話的令牌。此令牌用于創(chuàng)建媒體播放控制器
adjustAVPlaybackVolume(int direction, int flags)調(diào)節(jié)播放音量
setAVPlaybackVolume(int value, int flags)設(shè)置播放音量,要求支持絕對(duì)音量控制
getOptions()獲取與此控制器連接的AVSession的附加數(shù)據(jù)
getFlags()獲取AVSession的附加標(biāo)識(shí),標(biāo)記在AVSession中的定義
getAVMetadata()獲取媒體資源的元數(shù)據(jù)ohos.media.common.AVMetadata
getAVPlaybackInfo()獲取播放信息
getSessionOwnerPackageName()獲得AVSession實(shí)例的應(yīng)用程序的包名稱
getAVSessionInfo()獲取會(huì)話的附加數(shù)據(jù)
getPlayControls()獲取一個(gè)PlayControls實(shí)例,將用于控制播放,比如控制媒體播放、停止、下一首等
④ AVSession 的主要接口
接口名描述
AVSession(Context context, String tag)構(gòu)造AVSession實(shí)例,用于控制媒體播放
AVSession(Context context, String tag, PacMap sessionInfo)構(gòu)造帶有附加會(huì)話信息的AVSession實(shí)例,用于控制媒體播放
setAVSessionCallback(AVSessionCallback callback)設(shè)置回調(diào)函數(shù)來(lái)控制播放器,控制邏輯由應(yīng)用實(shí)現(xiàn)。如果callback為null則取消控制
setAVSessionAbility(IntentAgent ia)給AVSession設(shè)置一個(gè)IntentAgent,用來(lái)啟動(dòng)用戶界面
setAVButtonReceiver(IntentAgent ia)為媒體按鍵接收器設(shè)置一個(gè)IntentAgent,以便應(yīng)用結(jié)束后,可以通過(guò)媒體按鍵重新拉起應(yīng)用
enableAVSessionActive(boolean active)設(shè)置是否激活媒體會(huì)話。當(dāng)會(huì)話準(zhǔn)備接收命令時(shí),將輸入?yún)?shù)設(shè)置為true。如果會(huì)話停止接收命令,則設(shè)置為false
isAVSessionActive()查詢會(huì)話是否激活
sendAVSessionEvent(String event, PacMap options)向所有訂閱此會(huì)話的控制器發(fā)送事件
release()釋放資源,應(yīng)用播放完之后需調(diào)用
getAVToken()獲取應(yīng)用連接到會(huì)話的令牌。此令牌用于創(chuàng)建媒體播放控制器
getAVController()獲取會(huì)話構(gòu)造時(shí)創(chuàng)建的控制器,方便應(yīng)用使用
setAVPlaybackState(AVPlaybackState state)設(shè)置當(dāng)前播放狀態(tài)
setAVMetadata(AVMetadata avMetadata)設(shè)置媒體資源元數(shù)據(jù)ohos.media.common.AVMetadata
setAVQueue(List queue)設(shè)置播放隊(duì)列
setAVQueueTitle(CharSequence queueTitle)設(shè)置播放隊(duì)列的標(biāo)題,UI會(huì)顯示此標(biāo)題
setOptions(PacMap options)設(shè)置此會(huì)話關(guān)聯(lián)的附加數(shù)據(jù)
getCurrentControllerInfo()獲取發(fā)送當(dāng)前請(qǐng)求的媒體控制器信息
⑤ AVElement 的主要接口
接口名描述
AVElement(AVDescription description, int flags)構(gòu)造AVElement實(shí)例
getFlags()獲取flags的值
isScannable()判斷媒體是否可掃描,如:媒體有子節(jié)點(diǎn),則可繼續(xù)掃描獲取子節(jié)點(diǎn)內(nèi)容
isPlayable()檢查媒體是否可播放
getAVDescription()獲取媒體的詳細(xì)信息
getMediaId()獲取媒體的id

四、使用流程

  • 使用 AVSession 媒體框架創(chuàng)建一個(gè)播放器示例,分為創(chuàng)建客戶端和創(chuàng)建服務(wù)端。
① 創(chuàng)建客戶端
  • 在客戶端 AVClientAbility 中聲明 avBrowser 和 avController,通過(guò) avBrowser 并向服務(wù)端發(fā)送連接請(qǐng)求,然后將 avController 注冊(cè)到 ability:
public class AVClientAbility extends Ability {// 媒體瀏覽器private AVBrowser avBrowser;// 媒體控制器private AVController avController;// 服務(wù)端回傳的媒體列表List<AVElement> avElements;@Overridepublic void onStart(Intent intent) {super.onStart(intent);// 用于指向媒體瀏覽器服務(wù)的包路徑和類名ElementName elementName = new ElementName("", "com.samples.audioplayer", "com.samples.audioplayer.AVService");// connectionCallback在調(diào)用avBrowser.connect方法后進(jìn)行回調(diào)。avBrowser = new AVBrowser(context, elementName, connectionCallback, null);// avBrowser發(fā)送對(duì)媒體瀏覽器服務(wù)的連接請(qǐng)求,connect方法需要確保當(dāng)前處于斷開(kāi)連接狀態(tài)。avBrowser.connect();// 將媒體控制器注冊(cè)到ability以接收按鍵事件。AVController.setControllerForAbility(this, avController);}}
  • AVConnectionCallback 回調(diào)接口中的方法為可選實(shí)現(xiàn),通常需要會(huì)在 onConnected 中訂閱媒體數(shù)據(jù)和創(chuàng)建媒體控制器 AVController:
// 發(fā)起連接(avBrowser.connect)后的回調(diào)方法實(shí)現(xiàn)private AVConnectionCallback connectionCallback = new AVConnectionCallback() {@Overridepublic void onConnected() {// 成功連接媒體瀏覽器服務(wù)時(shí)回調(diào)該方法,否則回調(diào)onConnectionFailed()。// 重復(fù)訂閱會(huì)報(bào)錯(cuò),所以先解除訂閱。avBrowser.unsubscribeByParentMediaId(avBrowser.getRootMediaId());// 第二個(gè)參數(shù)AVSubscriptionCallback,用于處理訂閱信息的回調(diào)。avBrowser.subscribeByParentMediaId(avBrowser.getRootMediaId(), avSubscriptionCallback);AVToken token = avBrowser.getAVToken();avController = new AVController(AVClient.this, token); // AVController第一個(gè)參數(shù)為當(dāng)前類的context// 參數(shù)AVControllerCallback,用于處理服務(wù)端播放狀態(tài)及信息變化時(shí)回調(diào)。avController.setAVControllerCallback(avControllerCallback);// ...}// 其它回調(diào)方法(可選)// ...};
  • 通常在訂閱成功時(shí),在 AVSubscriptionCallback 回調(diào)接口 onAVElementListLoaded 中保存服務(wù)端回傳的媒體列表:
// 發(fā)起訂閱信息(avBrowser.subscribeByParentMediaId)后的回調(diào)方法實(shí)現(xiàn)private AVSubscriptionCallback avSubscriptionCallback = new AVSubscriptionCallback() {@Overridepublic void onAVElementListLoaded(String parentId, List<AVElement> children) {// 訂閱成功時(shí)回調(diào)該方法,parentID為標(biāo)識(shí),children為服務(wù)端回傳的媒體列表super.onAVElementListLoaded(parentId, children);avElements.addAll(children);// ...}};
  • AVControllerCallback 回調(diào)接口中的方法均為可選方法,主要用于服務(wù)端播放狀態(tài)及信息的變化后對(duì)客戶端的回調(diào),客戶端可在這些方法中實(shí)現(xiàn) UI 的刷新:
// 服務(wù)對(duì)客戶端的媒體數(shù)據(jù)或播放狀態(tài)變更后的回調(diào) private AVControllerCallback avControllerCallback = new AVControllerCallback() {@Overridepublic void onAVMetadataChanged(AVMetadata metadata) {// 當(dāng)服務(wù)端調(diào)用avSession.setAVMetadata(avMetadata)時(shí),此方法會(huì)被回調(diào)。super.onAVMetadataChanged(metadata);AVDescription description = metadata.getAVDescription();String title = description.getTitle().toString();PixelMap pixelMap = description.getIcon();// ...}@Overridepublic void onAVPlaybackStateChanged(AVPlaybackState playbackState) {// 當(dāng)服務(wù)端調(diào)用avSession.setAVPlaybackState(...)時(shí),此方法會(huì)被回調(diào)。super.onAVPlaybackStateChanged(playbackState);long position = playbackState.getCurrentPosition();// ...}// 其它回調(diào)方法(可選)// ...};
  • 完成以上實(shí)現(xiàn)后,則應(yīng)用可以在 UI 事件中調(diào)用 avController 的方法向服務(wù)端發(fā)送播放控制指令:
// 在UI播放與暫停按鈕的點(diǎn)擊事件中向服務(wù)端發(fā)送播放或暫停指令public void toPlayOrPause() {switch (avController.getAVPlaybackState().getAVPlaybackState()) {case AVPlaybackState.PLAYBACK_STATE_NONE: {avController.getPlayControls().prepareToPlay();avController.getPlayControls().play();break;}case AVPlaybackState.PLAYBACK_STATE_PLAYING: {avController.getPlayControls().pause();break;}case AVPlaybackState.PLAYBACK_STATE_PAUSED: {avController.getPlayControls().play();break;}default: {// ...}}}
  • 其它播放控制根據(jù)業(yè)務(wù)是否需要實(shí)現(xiàn),比如:
avController.getPlayControls().playNext();avController.getPlayControls().playPrevious();avController.getPlayControls().playFastForward();avController.getPlayControls().rewind();avController.getPlayControls().seekTo(1000);avController.getPlayControls().stop();// ...
  • 也可以主動(dòng)獲取媒體信息、播放狀態(tài)等數(shù)據(jù):
AVMetadata avMetadata = avController.getAVMetadata();AVPlaybackState avPlaybackState = avController.getAVPlaybackState();// ...
② 創(chuàng)建服務(wù)端
  • 在服務(wù)端 AVService 中聲明 AVSession 和 Player:
public class AVService extends AVBrowserService {// 根媒體IDprivate static final String AV_ROOT_ID = "av_root_id";// 媒體會(huì)話private AVSession avSession;// 媒體播放器private Player player;@Overridepublic void onStart(Intent intent) {super.onStart(intent);avSession = new AVSession(this, "AVService");setAVToken(avSession.getAVToken());// 設(shè)置sessioncallback,用于響應(yīng)客戶端的媒體控制器發(fā)起的播放控制指令。avSession.setAVSessionCallback(avSessionCallback);// 設(shè)置播放狀態(tài)初始狀態(tài)為AVPlaybackState.PLAYBACK_STATE_NONE。AVPlaybackState playbackState = new AVPlaybackState.Builder().setAVPlaybackState(AVPlaybackState.PLAYBACK_STATE_NONE, 0, 1.0f).build();avSession.setAVPlaybackState(playbackState);// 完成播放器的初始化,如果使用多個(gè)Player,也可以在執(zhí)行播放時(shí)初始化。player = new Player(this);}@Overridepublic AVBrowserRoot onGetRoot(String clientPackageName, int clientUid, PacMap rootHints) {// 響應(yīng)客戶端avBrowser.connect()方法。若同意連接,則返回有效的AVBrowserRoot實(shí)例,否則返回nullreturn new AVBrowserRoot(AV_ROOT_ID, null);}@Overridepublic void onLoadAVElementList(String parentId, AVBrowserResult result) {HiLog.info(TAG, "onLoadChildren");// 響應(yīng)客戶端avBrowser.subscribeByParentMediaId(...)方法。// 先執(zhí)行該方法detachForRetrieveAsync() result.detachForRetrieveAsync();// externalAudioItems緩存媒體文件,請(qǐng)開(kāi)發(fā)者自行實(shí)現(xiàn)。result.sendAVElementList(externalAudioItems.getAudioItems());}@Overridepublic void onLoadAVElementList(String s, AVBrowserResult avBrowserResult, PacMap pacMap) {// 響應(yīng)客戶端avBrowser.subscribeByParentMediaId(String, PacMap, AVSubscriptionCallback)方法。}@Overridepublic void onLoadAVElement(String s, AVBrowserResult avBrowserResult) {// 響應(yīng)客戶端avBrowser.getAVElement(String, AVElementCallback)方法。}}
  • 響應(yīng)客戶端的媒體控制器發(fā)起的播放控制指令的回調(diào)實(shí)現(xiàn):
private AVSessionCallback avSessionCallback = new AVSessionCallback() {@Overridepublic void onPlay() {super.onPlay();// 當(dāng)客戶端調(diào)用avController.getPlayControls().play()時(shí),該方法會(huì)被回調(diào)。// 響應(yīng)播放請(qǐng)求,開(kāi)始播放。if (avSession.getAVController().getAVPlaybackState() == AVPlaybackState.PLAYBACK_STATE_PAUSED) {if (player.play()) {AVPlaybackState playbackState = new AVPlaybackState.Builder().setAVPlaybackState(AVPlaybackState.PLAYBACK_STATE_PLAYING, player.getCurrentTime(),player.getPlaybackSpeed()).build();avSession.setAVPlaybackState(playbackState);}}}@Overridepublic void onPause() {super.onPause();// 當(dāng)客戶端調(diào)用avController.getPlayControls().pause()時(shí),該方法會(huì)被回調(diào)。// 響應(yīng)暫停請(qǐng)求,暫停播放。}@Overridepublic void onPlayNext() {super.onPlayNext();// 當(dāng)客戶端調(diào)用avController.getPlayControls().playNext()時(shí),該方法會(huì)被回調(diào)。// 響應(yīng)播放下一曲請(qǐng)求,通過(guò)avSession.setAVMetadata設(shè)置下一曲曲目的信息。avSession.setAVMetadata(avNextMetadata);}// 重寫(xiě)以處理按鍵事件@Overridepublic boolean onMediaButtonEvent(Intent mediaButtonIntent) {KeyEvent ke = mediaButtonIntent.getSequenceableParam(AVSession.PARAM_KEY_EVENT);if (ke == null) {HiLog.error(TAG, "getSequenceableParam failed");return false;}if (ke.isKeyDown()) {// 只處理按鍵抬起事件return true;}switch (ke.getKeyCode()) {case KeyEvent.KEY_MEDIA_PLAY_PAUSE: {if (playbackState.getAVPlaybackState() == AVPlaybackState.PLAYBACK_STATE_PAUSED) {onPlay();break;}if (playbackState.getAVPlaybackState() == AVPlaybackState.PLAYBACK_STATE_PLAYING) {onPause();break;}break;}case KeyEvent.KEY_MEDIA_PLAY: {onPlay();break;}case KeyEvent.KEY_MEDIA_PAUSE: {onPause();break;}case KeyEvent.KEY_MEDIA_STOP: {onStop();break;}case KeyEvent.KEY_MEDIA_NEXT: {onPlayNext();break;}case KeyEvent.KEY_MEDIA_PREVIOUS: {onPlayPrevious();break;}default: {break;}}return true;}// 其它回調(diào)方法(可選)// ...}

總結(jié)

以上是生活随笔為你收集整理的HarmonyOS之深入解析媒体会话的管理的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。