新聞中心
場景介紹

AVSession 框架有四個主要的類,控制著整個框架的核心,下圖簡單的說明四個核心媒體框架控制類的關(guān)系。
- AVBrowser
媒體瀏覽器,通常在客戶端創(chuàng)建,成功連接媒體服務(wù)后,通過媒體控制器 AVBrowse r向服務(wù)端發(fā)送播放控制指令。
其主要流程為,調(diào)用 connect 方法向 AVBrowserService 發(fā)起連接請求,連接成功后在回調(diào)方法 AVConnectionCallback.onConnected 中發(fā)起訂閱數(shù)據(jù)請求,并在回調(diào)方法 AVSubscriptionCallback.onAVElementListLoaded 中保存請求的媒體播放數(shù)據(jù)。
- AVController
媒體控制器,在客戶端 AVBrowser 連接服務(wù)成功后的回調(diào)方法 AVConnectionCallback.onConnected 中創(chuàng)建,用于向 Service 發(fā)送播放控制指令,并通過實現(xiàn) AVControllerCallback 回調(diào)來響應(yīng)服務(wù)端媒體狀態(tài)變化,例如曲目信息變更、播放狀態(tài)變更等,從而完成UI刷新。
- AVBrowser
Service
媒體瀏覽器服務(wù),通常在服務(wù)端,通過媒體會話 AVSession 與媒體瀏覽器建立連接,并通過實現(xiàn) Player 進行媒體播放。其中有兩個重要的方法:
- onGetRoot,處理從媒體瀏覽器 AVBrowser 發(fā)來的連接請求,通過返回一個有效的 AVBrowserRoot 對象表示連接成功;
- onLoadAVElementList,處理從媒體瀏覽器 AVBrowser 發(fā)來的數(shù)據(jù)訂閱請求,通過 AVBrowserResult.sendAVElementList(List
) 方法返回媒體播放數(shù)據(jù)。
- AVSession
媒體會話,通常在 AVBrowserService 的 onStart 中創(chuàng)建,通過 setAVToken 方法設(shè)置到 AVBrowserService 中,并通過實現(xiàn) AVSessionCallback 回調(diào)來接收和處理媒體控制器 AVController 發(fā)送的播放控制指令,如播放、暫停、跳轉(zhuǎn)至上一曲、跳轉(zhuǎn)至下一曲等。
除了上述四個類,AVSession 框架還有 AVElement。
- AVElement
媒體元素,用于將播放列表從 AVBrowserService 傳遞給 AVBrowser。
接口說明
| 接口名 | 描述 |
|---|---|
| AVBrowser(Context context, ElementName name, AVConnectionCallback callback, PacMap options) | 構(gòu)造 AVBrowser 實例,用于瀏覽 AVBrowserService 提供的媒體數(shù)據(jù)。 |
| void connect() | 連接 AVBrowserService。 |
| void disconnect() | 與 AVBrowserService 斷開連接。 |
| boolean isConnected() | 判斷當前是否已經(jīng)與 AVBrowserService 連接。 |
| ElementName getElementName() | 獲取 AVBrowserService 的ohos.bundle.ElementName實例。 |
| String getRootMediaId() | 獲取默認媒體 id。 |
| PacMap getOptions() | 獲取 AVBrowserService 提供的附加數(shù)據(jù)。 |
| AVToken getAVToken() | 獲取媒體會話的令牌。 |
| void getAVElement(String mediaId, AVElementCallback callback) | 輸入媒體的 id,查詢對應(yīng)的 ohos.media.common.sessioncore.AVElement 信息,查詢結(jié)果會通過 callback 返回。 |
| void subscribeByParentMediaId(String parentMediaId, AVSubscriptionCallback callback) | 查詢指定媒體 id 包含的所有媒體元素信息,并訂閱它的媒體信息更新通知。 |
| void subscribeByParentMediaId(String parentMediaId, PacMap options, AVSubscriptionCallback callback) | 基于特定于服務(wù)的參數(shù)來查詢指定媒體 id 中的媒體元素的信息,并訂閱它的媒體信息更新通知。 |
| void unsubscribeByParentMediaId(String parentMediaId) | 取消訂閱對應(yīng)媒體 id 的信息更新通知。 |
| void unsubscribeByParentMediaId(String parentMediaId, AVSubscriptionCallback callback) | 取消訂閱與指定 callback 相關(guān)的媒體 id 的信息更新通知。 |
| 接口名 | 描述 |
|---|---|
| abstract AVBrowserRoot onGetRoot(String callerPackageName, int clientUid, PacMap options) | 回調(diào)方法,用于返回應(yīng)用程序的媒體內(nèi)容的根信息,在 AVBrowser.connect()后進行回調(diào)。 |
| abstract void onLoadAVElementList(String parentMediaId, AVBrowserResult result) | 回調(diào)方法,用于返回應(yīng)用程序的媒體內(nèi)容的結(jié)果信息 AVBrowserResult,其中包含了子節(jié)點的 AVElement 列表,在 AVBrowser 的方法 subscribeByParentMediaId 或 notifyAVElementListUpdated 執(zhí)行后進行回調(diào)。 |
| abstract void onLoadAVElement(String mediaId, AVBrowserResult result) | 回調(diào)方法,用于獲取特定的媒體項目 AVElement 結(jié)果信息,在 AVBrowser.getAVElement 方法執(zhí)行后進行回調(diào)。 |
| AVToken getAVToken() | 獲取 AVBrowser 與 AVBrowserService 之間的會話令牌。 |
| void setAVToken(AVToken token) | 設(shè)置 AVBrowser 與 AVBrowserService 之間的會話令牌。 |
| final PacMap getBrowserOptions() | 獲取 AVBrowser 在連接 AVBrowserService 時設(shè)置的服務(wù)參數(shù)選項。 |
| final AVRemoteUserInfo getCallerUserInfo() | 獲取當前發(fā)送請求的調(diào)用者信息。 |
| void notifyAVElementListUpdated(String parentMediaId) | 通知所有已連接的 AVBrowser 當前父節(jié)點的子節(jié)點已經(jīng)發(fā)生改變。 |
| void notifyAVElementListUpdated(String parentId, PacMap options) | 通知所有已連接的 AVBrowser 當前父節(jié)點的子節(jié)點已經(jīng)發(fā)生改變,可設(shè)置服務(wù)參數(shù)。 |
| 接口名 | 描述 |
|---|---|
| AVController(Context context, AVToken avToken) | 構(gòu)造 AVController 實例,用于應(yīng)用程序與 AVSession 進行交互以控制媒體播放。 |
| static boolean setControllerForAbility(Ability ability, AVController controller) | 將媒體控制器注冊到 ability 以接收按鍵事件。 |
| boolean setAVControllerCallback(AVControllerCallback callback) | 注冊一個回調(diào)以接收來自 AVSession 的變更,例如元數(shù)據(jù)和播放狀態(tài)變更。 |
| boolean releaseAVControllerCallback(AVControllerCallback callback) | 釋放與 AVSession 之間的回調(diào)實例。 |
| List |
獲取播放隊列。 |
| CharSequence getAVQueueTitle() | 獲取播放隊列的標題。 |
| AVPlaybackState getAVPlaybackState() | 獲取播放狀態(tài)。 |
| boolean dispatchAVKeyEvent(KeyEvent keyEvent) | 應(yīng)用分發(fā)媒體按鍵事件給會話以控制播放。 |
| void sendCustomCommand(String command, PacMap pacMap, GeneralReceiver receiverCb) | 應(yīng)用向 AVSession 發(fā)送自定義命令,參考ohos.media.common.sessioncore.AVSessionCallback.onCommand。 |
| IntentAgent getAVSessionAbility() | 獲取啟動用戶界面的IntentAgent。 |
| AVToken getAVToken() | 獲取應(yīng)用連接到會話的令牌。此令牌用于創(chuàng)建媒體播放控制器。 |
| void adjustAVPlaybackVolume(int direction, int flags) | 調(diào)節(jié)播放音量。 |
| void setAVPlaybackVolume(int value, int flags) | 設(shè)置播放音量,要求支持絕對音量控制。 |
| PacMap getOptions() | 獲取與此控制器連接的AVSession的附加數(shù)據(jù)。 |
| long getFlags() | 獲取 AVSession 的附加標識,標記在 AVSession 中的定義。 |
| AVMetadata getAVMetadata() | 獲取媒體資源的元數(shù)據(jù)ohos.media.common.AVMetadata。 |
| AVPlaybackInfo getAVPlaybackInfo() | 獲取播放信息。 |
| String getSessionOwnerPackageName() | 獲得 AVSession 實例的應(yīng)用程序的包名稱。 |
| PacMap getAVSessionInfo() | 獲取會話的附加數(shù)據(jù)。 |
| PlayControls getPlayControls() | 獲取一個 PlayControls 實例,將用于控制播放,比如控制媒體播放、停止、下一首等。 |
| 接口名 | 描述 |
|---|---|
| AVSession(Context context, String tag) | 構(gòu)造 AVSession 實例,用于控制媒體播放。 |
| AVSession(Context context, String tag, PacMap sessionInfo) | 構(gòu)造帶有附加會話信息的 AVSession 實例,用于控制媒體播放。 |
| void setAVSessionCallback(AVSessionCallback callback) | 設(shè)置回調(diào)函數(shù)來控制播放器,控制邏輯由應(yīng)用實現(xiàn)。如果 callback 為 null 則取消控制。 |
| boolean setAVSessionAbility(IntentAgent ia) | 給 AVSession 設(shè)置一個IntentAgent,用來啟動用戶界面。 |
| boolean setAVButtonReceiver(IntentAgent ia) | 為媒體按鍵接收器設(shè)置一個 IntentAgent,以便應(yīng)用結(jié)束后,可以通過媒體按鍵重新拉起應(yīng)用。 |
| void enableAVSessionActive(boolean active) | 設(shè)置是否激活媒體會話。當會話準備接收命令時,將輸入?yún)?shù)設(shè)置為 true。如果會話停止接收命令,則設(shè)置為 false。 |
| boolean isAVSessionActive() | 查詢會話是否激活。 |
| void sendAVSessionEvent(String event, PacMap options) | 向所有訂閱此會話的控制器發(fā)送事件。 |
| void release() | 釋放資源,應(yīng)用播放完之后需調(diào)用。 |
| AVToken getAVToken() | 獲取應(yīng)用連接到會話的令牌。此令牌用于創(chuàng)建媒體播放控制器。 |
| AVController getAVController() | 獲取會話構(gòu)造時創(chuàng)建的控制器,方便應(yīng)用使用。 |
| void setAVPlaybackState(AVPlaybackState state) | 設(shè)置當前播放狀態(tài)。 |
| void setAVMetadata(AVMetadata avMetadata) | 設(shè)置媒體資源元數(shù)據(jù)ohos.media.common.AVMetadata。 |
| void setAVQueue(List |
設(shè)置播放隊列。 |
| void setAVQueueTitle(CharSequence queueTitle) | 設(shè)置播放隊列的標題,UI會顯示此標題。 |
| void setOptions(PacMap options) | 設(shè)置此會話關(guān)聯(lián)的附加數(shù)據(jù)。 |
| AVCallerUserInfo getCurrentControllerInfo() | 獲取發(fā)送當前請求的媒體控制器信息。 |
| 接口名 | 描述 |
|---|---|
| AVElement(AVDescription description, int flags) | 構(gòu)造 AVElement 實例。 |
| int getFlags() | 獲取flags的值。 |
| boolean isScannable() | 判斷媒體是否可掃描,如:媒體有子節(jié)點,則可繼續(xù)掃描獲取子節(jié)點內(nèi)容。 |
| boolean isPlayable() | 檢查媒體是否可播放。 |
| AVDescription getAVDescription() | 獲取媒體的詳細信息。 |
| String getMediaId() | 獲取媒體的id。 |
開發(fā)步驟
使用 AVSession 媒體框架創(chuàng)建一個播放器示例,分為創(chuàng)建客戶端和創(chuàng)建服務(wù)端。
創(chuàng)建客戶端
在客戶端 AVClientAbility 中聲明 AVBrowser 和 AVController,并向服務(wù)端發(fā)送連接請求。
public class AVClientAbility extends Ability {
// 媒體瀏覽器
private AVBrowser avBrowser;
// 媒體控制器
private AVController avController;
@Override
public void onStart(Intent intent) {
super.onStart(intent);
// 用于指向媒體瀏覽器服務(wù)的包路徑和類名
ElementName elementName = new ElementName("", "com.huawei.samples.audioplayer", "com.huawei.samples.audioplayer.AVService");
// connectionCallback 在調(diào)用 avBrowser.connect 方法后進行回調(diào)。
avBrowser = new AVBrowser(context, elementName, connectionCallback, null);
// avBrowser 發(fā)送對媒體瀏覽器服務(wù)的連接請求。
avBrowser.connect();
// 將媒體控制器注冊到 ability 以接收按鍵事件。
AVController.setControllerForAbility(this, avController);
}
}
AVConnectionCallback 回調(diào)接口中的方法為可選實現(xiàn),通常需要會在 onConnected 中訂閱媒體數(shù)據(jù)和創(chuàng)建媒體控制器 AVController。
// 發(fā)起連接(avBrowser.connect)后的回調(diào)方法實現(xiàn)
private AVConnectionCallback connectionCallback = new AVConnectionCallback() {
@Override
public void onConnected() {
// 成功連接媒體瀏覽器服務(wù)時回調(diào)該方法,否則回調(diào) onConnectionFailed()。
// 重復訂閱會報錯,所以先解除訂閱。
avBrowser.unsubscribeByParentMediaId(avBrowser.getRootMediaId());
// 第二個參數(shù) AVSubscriptionCallback,用于處理訂閱信息的回調(diào)。
avBrowser.subscribeByParentMediaId(AV_ROOTavBrowser.getRootMediaId(), avSubscriptionCallback);
AVToken token = avBrowser.getAVToken();
avController = new AVController(AVClient.this, token); // AVController第一個參數(shù)為當前類的context
// 參數(shù) AVControllerCallback,用于處理服務(wù)端播放狀態(tài)及信息變化時回調(diào)。
avController.setAVControllerCallback(avControllerCallback);
// ...
}
// 其它回調(diào)方法(可選)
// ...
};
通常在訂閱成功時,在 AVSubscriptionCallback 回調(diào)接口 onAVElementListLoaded 中保存服務(wù)端回傳的媒體列表。
// 發(fā)起訂閱信息(avBrowser.subscribeByParentMediaId)后的回調(diào)方法實現(xiàn)
private AVSubscriptionCallback avSubscriptionCallback = new AVSubscriptionCallback() {
@Override
public void onAVElementListLoaded(String parentId, List children) {
// 訂閱成功時回調(diào)該方法,parentID 為標識,children 為服務(wù)端回傳的媒體列表
super.onAVElementListLoaded(parentId, children);
list.addAll(children);
// ...
}
};
AVControllerCallback 回調(diào)接口中的方法均為可選方法,主要用于服務(wù)端播放狀態(tài)及信息的變化后對客戶端的回調(diào),客戶端可在這些方法中實現(xiàn)UI的刷新。
// 服務(wù)對客戶端的媒體數(shù)據(jù)或播放狀態(tài)變更后的回調(diào)
private AVControllerCallback avControllerCallback = new AVControllerCallback() {
@Override
public void onAVMetadataChanged(AVMetadata metadata) {
// 當服務(wù)端調(diào)用 avSession.setAVMetadata(avMetadata)時,此方法會被回調(diào)。
super.onAVMetadataChanged(metadata);
AVDescription description = metadata.getAVDescription();
String title = description.getTitle().toString();
PixelMap pixelMap = description.getIcon();
// ...
}
@Override
public void onAVPlaybackStateChanged(AVPlaybackState playbackState) {
// 當服務(wù)端調(diào)用avSession.setAVPlaybackState(...)時,此方法會被回調(diào)。
super.onAVPlaybackStateChanged(playbackState);
long position = playbackState.getCurrentPosition();
// ...
}
// 其它回調(diào)方法(可選)
// ...
};
完成以上實現(xiàn)后,則應(yīng)用可以在UI事件中調(diào)用avController的方法向服務(wù)端發(fā)送播放控制指令。
// 在 UI 播放與暫停按鈕的點擊事件中向服務(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ù)是否需要實現(xiàn),比如:
avController.getPlayControls().playNext();
avController.getPlayControls().playPrevious();
avController.getPlayControls().playFastForward();
avController.getPlayControls().rewind();
avController.getPlayControls().seekTo(1000);
avController.getPlayControls().stop();
// ...
也可以主動獲取媒體信息、播放狀態(tài)等數(shù)據(jù):
AVMetadata avMetadata = avController.getAVMetadata();
AVPlaybackState avPlaybackState = avController.getAVPlaybackState();
// ...
創(chuàng)建服務(wù)端
在服務(wù)端 AVService 中聲明 AVSession 和 Player。
public class AVService extends AVBrowserService {
// 媒體會話
private AVSession avSession;
// 媒體播放器
private Player player;
@Override
public 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);
// 完成播放器的初始化,如果使用多個 Player,也可以在執(zhí)行播放時初始化。
player = new Player(this);
}
@Override
public AVBrowserRoot onGetRoot(String clientPackageName, int clientUid, PacMap rootHints) {
// 響應(yīng)客戶端 avBrowser.connect()方法。若同意連接,則返回有效的AVBrowserRoot實例,否則返回null
return new AVBrowserRoot(AV_ROOT, null);
}
@Override
public void onLoadAVElementList(String parentId, AVBrowserResult result) {
LogUtil.info(TAG, "onLoadChildren");
// 響應(yīng)客戶端avBrowser.subscribeByParentMediaId(...)方法。
// 先執(zhí)行該方法detachForRetrieveAsync()
result.detachForRetrieveAsync();
// externalAudioItems緩存媒體文件,請開發(fā)者自行實現(xiàn)。
result.sendAVElementList(externalAudioItems.getAudioItems());
}
@Override
public void onLoadAVElementList(String s, AVBrowserResult avBrowserResult, PacMap pacMap) {
// 響應(yīng)客戶端avBrowser.subscribeByParentMediaId(String, PacMap, AVSubscriptionCallback)方法。
}
@Override
public void onLoadAVElement(String s, AVBrowserResult avBrowserResult) {
// 響應(yīng)客戶端avBrowser.getAVElement(String, AVElementCallback)方法。
}
}
響應(yīng)客戶端的媒體控制器發(fā)起的播放控制指令的回調(diào)實現(xiàn)。
private AVSessionCallback avSessionCallback = new AVSessionCallback() {
@Override
public void onPlay() {
super.onPlay();
// 當客戶端調(diào)用avController.getPlayControls().play()時,該方法會被回調(diào)。
// 響應(yīng)播放請求,開始播放。
if (avSession.getAVController().getAVPlaybackState().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);
}
}
}
@Override
public void onPause() {
super.onPause();
// 當客戶端調(diào)用avController.getPlayControls().pause()時,該方法會被回調(diào)。
// 響應(yīng)暫停請求,暫停播放。
}
@Override
public void onPlayNext() {
super.onPlayNext();
// 當客戶端調(diào)用avController.getPlayControls().playNext()時,該方法會被回調(diào)。
// 響應(yīng)播放下一曲請求,通過avSession.setAVMetadata 設(shè)置下一曲曲目的信息。
avSession.setAVMetadata(avNextMetadata);
}
// 重寫以處理按鍵事件
@Override
public boolean onMediaButtonEvent(Intent mediaButtonIntent) {
KeyEvent ke = mediaButtonIntent.getParcelableParam(AVSession.PARAM_KEY_EVENT);
if (ke == null) {
LogUtil.error("onMediaButtonEvent", "getParcelableParam 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)方法(可選)
// ...
} 文章標題:創(chuàng)新互聯(lián)鴻蒙OS教程:鴻蒙OS媒體會話開發(fā)指導
網(wǎng)站地址:http://m.fisionsoft.com.cn/article/cogiihg.html


咨詢
建站咨詢
