当前位置: 首页 > news >正文

凡科网电脑版怎么做网站上海最专业的seo公司

凡科网电脑版怎么做网站,上海最专业的seo公司,刚做的网站关键词就上来了,wordpress订阅者介绍 本示例使用fileIo获取指定音频文件,并通过AudioPlayer完成了音乐的播放完成了基本的音乐播放、暂停、上一曲、下一曲功能;并使用DeviceManager完成了分布式设备列表的显示和分布式能力完成了音乐播放状态的跨设备分享。 本示例用到了与用户进行交…

介绍

本示例使用fileIo获取指定音频文件,并通过AudioPlayer完成了音乐的播放完成了基本的音乐播放、暂停、上一曲、下一曲功能;并使用DeviceManager完成了分布式设备列表的显示和分布式能力完成了音乐播放状态的跨设备分享。

本示例用到了与用户进行交互的Ability的能力接口[@ohos.ability.featureAbility]

文件存储管理能力接口[@ohos.fileio]

屏幕属性接口[@ohos.display]

媒体查询接口[@ohos.mediaquery]

分布式数据管理接口[@ohos.data.distributedData]

音视频相关媒体业务能力接口[@ohos.multimedia.media]

分布式设备管理能力接口(设备管理),实现设备之间的kvStore对象的数据传输交互[@ohos.distributedDeviceManager]

效果预览

首页

使用说明

1.音乐播放,点击播放暂停、上一曲、下一曲按钮可以对音乐进行操作。

2.跨设备分享,组网并且双端均已授权条件下,点击分享按钮,选择设备,拉起对端设备上的音乐,并将本端的播放状态同步到对端上。

3.跨设备停止分享,分享成功前提条件下,点击停止分享按钮,将对端设备拉起的音乐应用停止退出。

相关概念

音频播放:媒体子系统包含了音视频相关媒体业务,通过AudioPlayer实现音频播放的能力。

数据分享:分布式数据管理为应用程序提供不同设备间数据库的分布式协同能力。通过调用分布式数据各个接口,应用程序可将数据保存到分布式数据库中,并可对分布式数据库中的数据进行增/删/改/查等各项操作。

资料文档参考

鸿蒙OS开发更多内容↓点击 《鸿蒙NEXT星河版开发学习文档》HarmonyOS与OpenHarmony技术

搜狗高速浏览器截图20240326151450.png

具体实现

鸿蒙NEXT文档可以
+mau12379是v喔直接领取!

在分布式音乐播放器中,分布式设备管理包含了分布式设备搜索、分布式设备列表弹窗、远端设备拉起三部分。
首先在分布式组网内搜索设备,然后把设备展示到分布式设备列表弹窗中,最后根据用户的选择拉起远端设备。

分布式设备搜索

通过SUBSCRIBE_ID搜索分布式组网内的远端设备,详见registerDeviceListCallback(callback) {}模块[源码参考]。

/** Copyright (c) 2022 Huawei Device Co., Ltd.* Licensed under the Apache License, Version 2.0 (the "License");* you may not use this file except in compliance with the License.* You may obtain a copy of the License at**     http://www.apache.org/licenses/LICENSE-2.0** Unless required by applicable law or agreed to in writing, software* distributed under the License is distributed on an "AS IS" BASIS,* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.* See the License for the specific language governing permissions and* limitations under the License.*/import deviceManager from '@ohos.distributedDeviceManager';import Logger from '../model/Logger';let SUBSCRIBE_ID: number = 100;const RANDOM: number = 65536;const TAG: string = 'RemoteDeviceModel';export class RemoteDeviceModel {public deviceLists: Array<deviceManager.DeviceBasicInfo> = [];public discoverLists: Array<deviceManager.DeviceBasicInfo> = [];private callback: () => void = null;private authCallback: () => void = null;private deviceManager: deviceManager.DeviceManager = undefined;registerDeviceListCallback(callback) {if (typeof (this.deviceManager) === 'undefined') {Logger.info(TAG, 'deviceManager.createDeviceManager begin');try {this.deviceManager = deviceManager.createDeviceManager('ohos.samples.distributedmusicplayer');this.registerDeviceList(callback);Logger.info(TAG, `createDeviceManager callback returned, value= ${JSON.stringify(this.deviceManager)}`);} catch (error) {Logger.info(TAG, `createDeviceManager throw error, error=${error} message=${error.message}`);}Logger.info(TAG, 'deviceManager.createDeviceManager end');} else {this.registerDeviceList(callback);};};registerDeviceList(callback) {Logger.info(TAG, 'registerDeviceListCallback');this.callback = callback;if (this.deviceManager === undefined) {Logger.error(TAG, 'deviceManager has not initialized');this.callback();return;};Logger.info(TAG, 'getTrustedDeviceListSync begin');let list: deviceManager.DeviceBasicInfo[] = [];try {list = this.deviceManager.getAvailableDeviceListSync();} catch (error) {Logger.info(TAG, `getTrustedDeviceListSync throw error, error=${error} message=${error.message}`);};Logger.info(TAG, `getTrustedDeviceListSync end, deviceLists= ${JSON.stringify(list)}`);if (typeof (list) !== 'undefined' && typeof (list.length) !== 'undefined') {this.deviceLists = list;};this.callback();Logger.info(TAG, 'callback finished');try {this.deviceManager.on('deviceStateChange', (data) => {Logger.info(TAG, `deviceStateChange data= ${JSON.stringify(data)}`);switch (data.action) {case deviceManager.DeviceStateChange.AVAILABLE:this.discoverLists = [];this.deviceLists.push(data.device);Logger.info(TAG, `reday, updated device list= ${JSON.stringify(this.deviceLists)} `);let list: deviceManager.DeviceBasicInfo[] = [];try {list = this.deviceManager.getAvailableDeviceListSync();} catch (err) {Logger.info(TAG, `this err is ${JSON.stringify(err)}`);}Logger.info(TAG, `getTrustedDeviceListSync end, deviceList= ${JSON.stringify(list)}`);if (typeof (list) !== 'undefined' && typeof (list.length) !== 'undefined') {this.deviceLists = list;}this.callback();break;case deviceManager.DeviceStateChange.UNAVAILABLE:if (this.deviceLists.length > 0) {let list = [];for (let i = 0; i < this.deviceLists.length; i++) {if (this.deviceLists[i].deviceId !== data.device.deviceId) {list[i] = data.device;};};this.deviceLists = list;};Logger.info(TAG, `offline, updated device list= ${JSON.stringify(this.deviceLists)}`);this.callback();break;default:break;};});this.deviceManager.on('discoverSuccess', (data) => {Logger.info(TAG, `discoverSuccess data= ${JSON.stringify(data)}`);Logger.info(TAG, `discoverSuccess this.deviceLists= ${this.deviceLists}, this.deviceLists.length= ${this.deviceLists.length}`);for (let i = 0;i < this.discoverLists.length; i++) {if (this.discoverLists[i].deviceId === data.device.deviceId) {Logger.info(TAG, 'device founded, ignored');return;};};this.discoverLists[this.discoverLists.length] = data.device;this.callback();});this.deviceManager.on('discoverFailure', (data) => {Logger.info(TAG, `discoverFailure data= ${JSON.stringify(data)}`);});this.deviceManager.on('serviceDie', () => {Logger.error(TAG, 'serviceDie');});} catch (error) {Logger.info(TAG, `on throw error, error=${error} message=${error.message}`);}let discoverParam = {'discoverTargetType': 1};let filterOptions = {'availableStatus': 0};Logger.info(TAG, `startDiscovering ${SUBSCRIBE_ID}`);try {if (this.deviceManager !== null) {this.deviceManager.startDiscovering(discoverParam, filterOptions);};} catch (error) {Logger.error(TAG, `startDiscovering throw error, error=${error} message=${error.message}`);};};authDevice(device, callback) {Logger.info(TAG, `authDevice ${device}`);if (device !== undefined) {for (let i = 0; i < this.discoverLists.length; i++) {if (this.discoverLists[i].deviceId === device.deviceId) {Logger.info(TAG, 'device founded, ignored');let bindParam = {bindType: 1,targetPkgName: 'ohos.samples.distributedmusicplayer',appName: 'Music',};Logger.info(TAG, `authenticateDevice ${JSON.stringify(this.discoverLists[i])}`);try {this.deviceManager.bindTarget(device.deviceId, bindParam, (err, data) => {if (err) {Logger.error(TAG, `authenticateDevice error: ${JSON.stringify(err)}`);this.authCallback = () => {};return;};Logger.info(TAG, `authenticateDevice succeed, data= ${JSON.stringify(data)}`);this.authCallback = callback;});} catch (error) {Logger.error(TAG, `authenticateDevice throw error, error=${JSON.stringify(error)} message=${error.message}`);}}}}};unregisterDeviceListCallback() {Logger.info(TAG, `stopDiscovering ${SUBSCRIBE_ID}`);if (this.deviceManager === undefined) {return;};try {this.deviceManager.stopDiscovering();this.deviceManager.off('deviceStateChange');this.deviceManager.off('discoverSuccess');this.deviceManager.off('discoverFailure');this.deviceManager.off('serviceDie');} catch (error) {Logger.info(TAG, `stopDeviceDiscovery throw error, error=${error} message=${error.message}`);}this.deviceLists = [];};}
分布式设备列表弹窗

使用@CustomDialog弹出分布式设备列表弹窗,参考首页。[源码参考]。

/** Copyright (c) 2022 Huawei Device Co., Ltd.* Licensed under the Apache License, Version 2.0 (the "License");* you may not use this file except in compliance with the License.* You may obtain a copy of the License at**     http://www.apache.org/licenses/LICENSE-2.0** Unless required by applicable law or agreed to in writing, software* distributed under the License is distributed on an "AS IS" BASIS,* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.* See the License for the specific language governing permissions and* limitations under the License.*/import deviceManager from '@ohos.distributedDeviceManager';import Logger from '../model/Logger';const TAG: string = 'DeviceDialog';@CustomDialogexport struct DeviceDialog {controller?: CustomDialogController;private deviceLists: Array<deviceManager.DeviceBasicInfo> = [];private selectedIndex: number = 0;private selectedIndexChange: (selectedIndex: number) => void = () => {};build() {Column() {Text($r('app.string.choiceDevice')).fontSize('32px').width('434px').fontColor(Color.Black).textAlign(TextAlign.Start).fontWeight(600)List() {ForEach(this.deviceLists, (item: deviceManager.DeviceBasicInfo, index: number | undefined) => {ListItem() {Flex({direction: FlexDirection.Row,justifyContent: FlexAlign.SpaceBetween,alignItems: ItemAlign.Center}) {Text(item.deviceName).fontSize(16).width('86%').fontColor(Color.Black).textAlign(TextAlign.Start)Radio({ value: '', group: 'radioGroup' }).radioStyle({checkedBackgroundColor: '#ff0d64fb'}).width('7%').checked(index === this.selectedIndex ? true : false)}.height(55).onClick(() => {Logger.info(TAG, `select device: ${item.deviceId}`)if (index === this.selectedIndex) {Logger.info(TAG, 'index === this.selectedIndex')return}this.selectedIndex = index !== undefined ? index : 0if (this.controller !== undefined) {this.controller.close()}this.selectedIndexChange(this.selectedIndex)})}.width('434px').height('80px')})}.margin({ top: 12 }).width('434px').height('18%')Button() {Text($r('app.string.cancel')).width('90%').fontSize(21).fontColor('#ff0d64fb').textAlign(TextAlign.Center)}.margin({ bottom: 16 }).type(ButtonType.Capsule).backgroundColor(Color.White).onClick(() => {if (this.controller !== undefined) {this.controller.close()}})}.margin({ bottom: 36 }).width('500px').padding(10).backgroundColor(Color.White).border({ color: Color.White, radius: 20 })}}
远端设备拉起

通过startAbility(deviceId)方法拉起远端设备的包,[源码参考]。

/** Copyright (c) 2022-2023 Huawei Device Co., Ltd.* Licensed under the Apache License, Version 2.0 (the "License");* you may not use this file except in compliance with the License.* You may obtain a copy of the License at**     http://www.apache.org/licenses/LICENSE-2.0** Unless required by applicable law or agreed to in writing, software* distributed under the License is distributed on an "AS IS" BASIS,* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.* See the License for the specific language governing permissions and* limitations under the License.*/import abilityAccessCtrl, { Permissions } from '@ohos.abilityAccessCtrl';import display from '@ohos.display';import common from '@ohos.app.ability.common';import mediaQuery from '@ohos.mediaquery';import rpc from '@ohos.rpc';import Want from '@ohos.app.ability.Want';import PermissionRequestResult from 'security/PermissionRequestResult';import KvStoreModel from '../model/KvStoreModel';import Logger from '../model/Logger';import PlayerModel from '../model/PlayerModel';import deviceManager from '@ohos.distributedDeviceManager';import ability from '@ohos.ability.ability';import { RemoteDeviceModel } from '../model/RemoteDeviceModel';import { DeviceDialog } from '../common/DeviceDialog';import {APPLICATION_BUNDLE_NAME,APPLICATION_SERVICE_NAME,MusicSharedEventCode,MusicSharedStatus,MusicConnectEvent} from '../common/MusicSharedDefinition';const TAG: string = 'Index';const DESIGN_WIDTH: number = 720.0;const SYSTEM_UI_HEIGHT: number = 134;const DESIGN_RATIO: number = 16 / 9;const ONE_HUNDRED: number = 100;const ONE_THOUSAND: number = 1000;const SIXTY: number = 60;const REMOTE_ABILITY_STARTED: string = 'remoteAbilityStarted';const ABILITY_SHARED_BUTTON = 0;const DEFAULT_NUM = -1;const PREVIOUS_CLICK = 2;interface Params {uri: string,seekTo: number,isPlaying: boolean};@Entry@Componentstruct Index {private listener = mediaQuery.matchMediaSync('screen and (min-aspect-ratio: 1.5) or (orientation: landscape)');@State isLand: boolean = false;@State currentTimeText: string = '';@State currentProgress: number = 0;@State totalMs: number = 0;@State riscale: number = 1;@State risw: number = 720;@State rish: number = 1280;@State isSwitching: boolean = false;@State deviceLists: Array<deviceManager.DeviceBasicInfo> = [];@State isDialogShowing: boolean = false;@State isDistributed: boolean = false;@State title: string = '';@State totalTimeText: string = '00:00';@State albumSrc: Resource = $r('app.media.album');@State selectedIndex: number = 0;@State imageArrays: Array<Resource> = [$r('app.media.ic_hop'), $r('app.media.ic_play_previous'), $r('app.media.ic_play'), $r('app.media.ic_play_next')];private dialogController: CustomDialogController | null = null;@StorageLink('exitMusicApp') @Watch('exitMusicApp') isExitMusicApp: boolean = false;@StorageLink('remoteServiceExtensionConnectEvent') @Watch('remoteServiceExtensionConnectEvent') isRemoteServiceExtensionConnectEvent: boolean = false;@StorageLink('musicPlay') @Watch('musicPlay') isMusicPlay: boolean = false;@StorageLink('musicPause') @Watch('musicPause') isMusicPause: boolean = false;private remoteDeviceModel: RemoteDeviceModel = new RemoteDeviceModel();private context: common.UIAbilityContext | null = null;private deviceId: string | null = null;private clickFlag = MusicSharedStatus.MUSIC_SHARED;private localExtensionRemote: rpc.IRemoteObject | null = null;onLand = (mediaQueryResult: mediaQuery.MediaQueryResult) => {Logger.info(TAG, `onLand: mediaQueryResult.matches= ${mediaQueryResult.matches}`);if (mediaQueryResult.matches) {this.isLand = true;} else {this.isLand = false;};};showDialog() {this.remoteDeviceModel.registerDeviceListCallback(() => {Logger.info(TAG, 'registerDeviceListCallback, callback entered');this.deviceLists = [];this.deviceLists.push({deviceId: '0',deviceName: 'local device',deviceType: '0',networkId: ''});let deviceTempList = this.remoteDeviceModel.discoverLists.length > 0 ? this.remoteDeviceModel.discoverLists : this.remoteDeviceModel.deviceLists;for (let i = 0; i < deviceTempList.length; i++) {Logger.info(TAG, `device ${i}/${deviceTempList.length} deviceId= ${deviceTempList[i].deviceId},deviceName= ${deviceTempList[i].deviceName}, deviceType= ${deviceTempList[i].deviceType}`);this.deviceLists.push(deviceTempList[i]);Logger.info(TAG, 'deviceLists push end');};Logger.info(TAG, 'CustomDialogController start');if (this.dialogController !== null) {this.dialogController.close();this.dialogController = null;}this.dialogController = new CustomDialogController({builder: DeviceDialog({deviceLists: this.deviceLists,selectedIndex: this.selectedIndex,selectedIndexChange: this.selectedIndexChange}),autoCancel: true,customStyle: true});this.dialogController.open();Logger.info(TAG, 'CustomDialogController end');})};showPromptDialog(title: ResourceStr, str: ResourceStr) {AlertDialog.show({title: title,message: str,confirm: {value: $r('app.string.cancel'),action: () => {Logger.info(TAG, `Button-clicking callback`);}},cancel: () => {Logger.info(TAG, `Closed callbacks`);}});};remoteServiceExtensionConnectEvent(event: string) {if (typeof (event) === 'string') {let viewThis = AppStorage.get<Index>('viewThis');if (viewThis !== undefined) {if (event === MusicConnectEvent.EVENT_CONNECT) {viewThis.clickFlag = MusicSharedStatus.MUSIC_STOP_SHARED;viewThis.imageArrays[ABILITY_SHARED_BUTTON] = $r('app.media.ic_hop');Logger.info(TAG, 'remote service on connect callbacked');} else if (event === MusicConnectEvent.EVENT_DISCONNECT) {viewThis.imageArrays[ABILITY_SHARED_BUTTON] = $r('app.media.ic_hop');viewThis.clickFlag = MusicSharedStatus.MUSIC_SHARED;viewThis.showPromptDialog($r('app.string.ConnectRemoteDevices'), $r('app.string.onDisconnectService'));} else if (event === MusicConnectEvent.EVENT_FAILED) {viewThis.imageArrays[ABILITY_SHARED_BUTTON] = $r('app.media.ic_hop');viewThis.clickFlag = MusicSharedStatus.MUSIC_SHARED;viewThis.showPromptDialog($r('app.string.ConnectRemoteDevices'), $r('app.string.onFailedService'));} else if (event === MusicConnectEvent.EVENT_TIMEOUT) {this.imageArrays[ABILITY_SHARED_BUTTON] = $r('app.media.ic_hop');viewThis.clickFlag = MusicSharedStatus.MUSIC_SHARED;viewThis.showPromptDialog($r('app.string.ConnectRemoteDevices'), $r('app.string.ConnectionTimeout'));}}} else {Logger.info(TAG, 'event is not a string');};};musicPause() {Logger.info(TAG, 'music pause recv');PlayerModel.pause();let viewThis = AppStorage.get<Index>('viewThis');viewThis!.imageArrays[PREVIOUS_CLICK] = $r('app.media.ic_play');};musicPlay() {Logger.info(TAG, 'music play recv');PlayerModel.play(DEFAULT_NUM, true);let viewThis = AppStorage.get<Index>('viewThis');viewThis!.imageArrays[PREVIOUS_CLICK] = $r('app.media.ic_pause');};exitMusicApp() {Logger.info(TAG, `exit music app called`);if (this.localExtensionRemote !== null && typeof (this.localExtensionRemote) === 'object') {let option = new rpc.MessageOption();let data = new rpc.MessageParcel();let reply = new rpc.MessageParcel();this.localExtensionRemote.sendRequest(MusicSharedEventCode.STOP_LOCAL_SERIVCE,data,reply,option);} else {Logger.info(TAG, `Remote start type is error or deviceID is empty, typeof= ${typeof (this.localExtensionRemote)}`);};};connectLocalExtension() {let localServiceWant: Want = {bundleName: APPLICATION_BUNDLE_NAME,abilityName: APPLICATION_SERVICE_NAME,};let connectOptions: ability.ConnectOptions = {onConnect: (elementName, remote) => {this.localExtensionRemote = remote;Logger.info(TAG, `onConnect called elementName is ${JSON.stringify(elementName)}`);},onDisconnect: (elementName) => {if (this.context !== null) {this.context.terminateSelf();Logger.info(TAG, `OnDisconnect called elementName is ${JSON.stringify(elementName)}`);};},onFailed: (code) => {if (this.context !== null) {this.context.terminateSelf();Logger.info(TAG, `OnFailed called code is ${JSON.stringify(code)}`);}}};if (this.context !== null) {this.context.connectServiceExtensionAbility(localServiceWant, connectOptions);};};startRemoteExtension(deviceId: string, params: object) {if (this.localExtensionRemote !== null && typeof (this.localExtensionRemote) === 'object' && typeof (deviceId) === 'string' && deviceId !== '') {let option = new rpc.MessageOption();let data = new rpc.MessageParcel();let reply = new rpc.MessageParcel();data.writeString(deviceId);data.writeString(JSON.stringify(params));this.localExtensionRemote.sendRequest(MusicSharedEventCode.START_DISTRIBUTED_MUSIC_SERVICE, data, reply, option);this.deviceId = deviceId;this.imageArrays[ABILITY_SHARED_BUTTON] = $r('app.media.ic_hop');} else {Logger.info(TAG, `Remote start type is error or deviceID is empty, typeof= ${typeof (this.localExtensionRemote)}`);};};stopRemoteExtension() {if (this.localExtensionRemote !== null && typeof (this.localExtensionRemote) === 'object' && typeof (this.deviceId) === 'string' && this.deviceId !== '') {let option = new rpc.MessageOption();let data = new rpc.MessageParcel();let reply = new rpc.MessageParcel();data.writeString(this.deviceId);this.localExtensionRemote.sendRequest(MusicSharedEventCode.STOP_DISTRIBUTED_MUSIC_SERVICE, data, reply, option);this.deviceId = '';} else {Logger.info(TAG, `Remote stopped type is wrong or deviceID is empty, typeof= ${typeof (this.localExtensionRemote)}`);};};sendMessagePlay() {if (this.localExtensionRemote !== null) {let option = new rpc.MessageOption();let data = new rpc.MessageParcel();let reply = new rpc.MessageParcel();this.localExtensionRemote.sendRequest(MusicSharedEventCode.PLAY_MUSIC_SERVICE, data, reply, option);Logger.info(TAG, `onPlayClick send mssage success`);} else {Logger.info(TAG, `can not get proxy`);return;};};sendMessagePause() {if (this.localExtensionRemote === null) {Logger.info(TAG, `can not get proxy`);return;};let option = new rpc.MessageOption();let data = new rpc.MessageParcel();let reply = new rpc.MessageParcel();this.localExtensionRemote.sendRequest(MusicSharedEventCode.PAUSE_MUSIC_SERVICE, data, reply, option);Logger.info(TAG, `onPauseClick send mssage success`);};onBackPress() {if (this.isDialogShowing === true) {this.dismissDialog();return true;};return false;};onPageHide() {if (this.isDialogShowing === true) {this.dismissDialog();return true;};return false;};dismissDialog() {if (this.dialogController !== null) {this.dialogController.close();}this.remoteDeviceModel.unregisterDeviceListCallback();this.isDialogShowing = false;};startAbilityContinuation(deviceId: string) {let params: Params = {uri: '',seekTo: 0,isPlaying: false};Logger.info(TAG, `startAbilityContinuation PlayerModel.index= ${PlayerModel.index}/${PlayerModel.playlist.audioFiles.length}`);if (PlayerModel.index >= 0 && PlayerModel.index <= PlayerModel.playlist.audioFiles.length) {params = {uri: PlayerModel.playlist.audioFiles[PlayerModel.index].fileUri,seekTo: PlayerModel.getCurrentMs(),isPlaying: PlayerModel.isPlaying};};Logger.info(TAG, `context.startAbility deviceId= ${deviceId}`);if (this.context !== null) {KvStoreModel.setOnMessageReceivedListener(this.context, REMOTE_ABILITY_STARTED, () => {Logger.info(TAG, 'OnMessageReceived, terminateSelf');});};Logger.info(TAG, `context.startAbility start`);this.clickFlag = MusicSharedStatus.MUSIC_REMOTING;this.startRemoteExtension(deviceId, params);this.clearSelectState();Logger.info(TAG, 'context.startAbility end');};selectedIndexChange = (selectedIndex: number) => {if (this.context !== null && selectedIndex === 0) {this.context.startAbility({ bundleName: 'ohos.samples.distributedmusicplayer',abilityName: 'ohos.samples.distributedmusicplayer.MainAbility',deviceId: this.deviceLists[selectedIndex].deviceId,parameters: {isFA: 'EXIT'}}).then(() => {Logger.info(TAG, `startAbility finished`);}).catch((err: Error) => {Logger.info(TAG, `startAbility filed error = ${JSON.stringify(err)}`);});this.isDistributed = false;this.selectedIndex = 0;if (this.dialogController !== null) {this.dialogController.close();}this.deviceLists = [];return;};this.selectedIndex = selectedIndex;this.selectDevice();};selectDevice() {Logger.info(TAG, 'start ability ......');if (this.selectedIndex !== undefined && (this.remoteDeviceModel === null || this.remoteDeviceModel.discoverLists.length <= 0)) {Logger.info(TAG, `start ability device:${JSON.stringify(this.deviceLists)}`);this.startAbilityContinuation(this.deviceLists[this.selectedIndex].networkId as string);this.clearSelectState();return;};Logger.info(TAG, 'start ability, needAuth');if (this.selectedIndex !== undefined){this.remoteDeviceModel.authDevice(this.deviceLists[this.selectedIndex], (device: deviceManager.DeviceBasicInfo) => {Logger.info(TAG, 'auth and online finished');this.startAbilityContinuation(device.networkId);});}Logger.info(TAG, 'start ability2 ......');this.clearSelectState();};clearSelectState() {this.deviceLists = [];if (this.dialogController) {this.dialogController.close();this.dialogController = null;};};getShownTimer(ms: number) {let minStr: string;let secStr: string;let seconds = Math.floor(ms / ONE_THOUSAND);let sec = seconds % SIXTY;Logger.info(TAG, `getShownTimer sec = ${sec}`);let min = (seconds - sec) / SIXTY;Logger.info(TAG, `getShownTimer min = ${min}`);if (sec < 10) {secStr = '0' + sec;} else {secStr = sec.toString(10);};if (min < 10) {minStr = '0' + min;} else {minStr = min.toString(10);};Logger.warn(TAG, `getShownTimer = ${minStr}:${secStr}`);return minStr + ':' + secStr;};refreshSongInfo(index: number) {Logger.info(TAG, `refreshSongInfo ${index}/${PlayerModel.playlist.audioFiles.length}`);if (index >= PlayerModel.playlist.audioFiles.length) {Logger.warn(TAG, 'refreshSongInfo ignored');return;};// update song titlethis.title = PlayerModel.playlist.audioFiles[index].name;this.albumSrc = (index % 2 === 0) ? $r('app.media.album') : $r('app.media.album2');// update durationthis.totalMs = PlayerModel.getDuration();this.totalTimeText = this.getShownTimer(this.totalMs);this.currentTimeText = this.getShownTimer(PlayerModel.getCurrentMs());Logger.info(TAG, `refreshSongInfo this.title= ${this.title}, this.totalMs= ${this.totalMs}, this.totalTimeText= ${this.totalTimeText},this.currentTimeText= ${this.currentTimeText}`);};onAppSharedClick() {if (this.clickFlag === MusicSharedStatus.MUSIC_SHARED) {Logger.info(TAG, `1start button is ${JSON.stringify(this.imageArrays[ABILITY_SHARED_BUTTON])}`);this.showDialog();} else if (this.clickFlag === MusicSharedStatus.MUSIC_STOP_SHARED) {Logger.info(TAG, `2start button is ${JSON.stringify(this.imageArrays[ABILITY_SHARED_BUTTON])}`);this.stopRemoteExtension();this.imageArrays[ABILITY_SHARED_BUTTON] = $r('app.media.ic_hop');};};onPreviousClick() {if (this.isSwitching) {Logger.info(TAG, 'onPreviousClick ignored, isSwitching');return;};Logger.info(TAG, 'onPreviousClick');PlayerModel.index--;if (PlayerModel.index < 0 && PlayerModel.playlist.audioFiles.length >= 1) {PlayerModel.index = PlayerModel.playlist.audioFiles.length - 1;};this.currentProgress = 0;this.isSwitching = true;PlayerModel.preLoad(PlayerModel.index, () => {this.refreshSongInfo(PlayerModel.index);PlayerModel.play(0, true);if (PlayerModel.isPlaying) {this.imageArrays[PREVIOUS_CLICK] = $r('app.media.ic_pause');};this.isSwitching = false;});};onNextClick() {if (this.isSwitching) {Logger.info(TAG, 'onNextClick ignored, isSwitching');return;};Logger.info(TAG, 'onNextClick');PlayerModel.index++;if (PlayerModel.index >= PlayerModel.playlist.audioFiles.length) {PlayerModel.index = 0;};this.currentProgress = 0;this.isSwitching = true;PlayerModel.preLoad(PlayerModel.index, () => {this.refreshSongInfo(PlayerModel.index);PlayerModel.play(0, true);if (PlayerModel.isPlaying) {this.imageArrays[PREVIOUS_CLICK] = $r('app.media.ic_pause');};this.isSwitching = false;});};onPlayClick() {if (this.isSwitching) {Logger.info(TAG, 'onPlayClick ignored, isSwitching');return;};Logger.info(TAG, `onPlayClick isPlaying= ${PlayerModel.isPlaying}`);if (PlayerModel.isPlaying) {PlayerModel.pause();this.imageArrays[PREVIOUS_CLICK] = $r('app.media.ic_play');this.sendMessagePause();} else {PlayerModel.preLoad(PlayerModel.index, () => {PlayerModel.play(DEFAULT_NUM, true);this.imageArrays[PREVIOUS_CLICK] = $r('app.media.ic_pause');this.sendMessagePlay();})};};restoreFromWant() {Logger.info(TAG, 'restoreFromWant');let status: Record<string, Object> | undefined = AppStorage.get('status');if (status !== undefined && status !== null && status.uri !== null) {KvStoreModel.broadcastMessage(this.context, REMOTE_ABILITY_STARTED);Logger.info(TAG, 'restorePlayingStatus');PlayerModel.restorePlayingStatus(status, (index: number) => {Logger.info(TAG, `restorePlayingStatus finished, index= ${index}`);if (index >= 0) {this.refreshSongInfo(index);} else {PlayerModel.preLoad(0, () => {this.refreshSongInfo(0);})}if (status !== undefined) {Logger.info(TAG, `Index PlayerModel.restorePlayingStatus this.totalMs = ${this.totalMs}, status.seekTo = ${status.seekTo}`);this.currentProgress = Math.floor(Number(status.seekTo) / this.totalMs * ONE_HUNDRED);}})} else {PlayerModel.preLoad(0, () => {this.refreshSongInfo(0);});}};aboutToAppear() {Logger.info(TAG, `begin`);Logger.info(TAG, 'grantPermission');this.context = getContext(this) as common.UIAbilityContext;let atManager: abilityAccessCtrl.AtManager = abilityAccessCtrl.createAtManager();let permission: Array<Permissions> = ['ohos.permission.DISTRIBUTED_DATASYNC'];try {atManager.requestPermissionsFromUser(this.context, permission).then((data: PermissionRequestResult) => {Logger.info(TAG, `data: ${JSON.stringify(data)}`);}).catch((err: object) => {Logger.info(TAG, `err: ${JSON.stringify(err)}`);})} catch (err) {Logger.info(TAG, `catch err->${JSON.stringify(err)}`);}display.getDefaultDisplay().then((dis: display.Display) => {Logger.info(TAG, `getDefaultDisplay dis= ${JSON.stringify(dis)}`);let proportion = DESIGN_WIDTH / dis.width;let screenWidth = DESIGN_WIDTH;let screenHeight = (dis.height - SYSTEM_UI_HEIGHT) * proportion;this.riscale = (screenHeight / screenWidth) / DESIGN_RATIO;if (this.riscale < 1) {// The screen ratio is shorter than design ratiothis.risw = screenWidth * this.riscale;this.rish = screenHeight;} else {// The screen ratio is longer than design ratiothis.risw = screenWidth;this.rish = screenHeight / this.riscale;}Logger.info(TAG, `proportion=${proportion} , screenWidth= ${screenWidth},screenHeight= ${screenHeight} , riscale= ${this.riscale} , risw= ${this.risw} , rish= ${this.rish}`);})Logger.info(TAG, 'getDefaultDisplay end');this.currentTimeText = this.getShownTimer(0);PlayerModel.setOnStatusChangedListener((isPlaying: string) => {Logger.info(TAG, `on player status changed, isPlaying= ${isPlaying} refresh ui`);PlayerModel.setOnPlayingProgressListener((currentTimeMs: number) => {this.currentTimeText = this.getShownTimer(currentTimeMs);this.currentProgress = Math.floor(currentTimeMs / this.totalMs * ONE_HUNDRED);});if (isPlaying) {this.imageArrays[PREVIOUS_CLICK] = $r('app.media.ic_pause');} else {this.imageArrays[PREVIOUS_CLICK] = $r('app.media.ic_play');}});PlayerModel.getPlaylist(() => {Logger.info(TAG, 'on playlist generated, refresh ui');this.restoreFromWant();});AppStorage.setOrCreate('viewThis', this);this.connectLocalExtension();};aboutToDisappear() {Logger.info(TAG, `aboutToDisappear begin`)if (PlayerModel === undefined) {return}PlayerModel.release()this.remoteDeviceModel.unregisterDeviceListCallback()this.dialogController = nullKvStoreModel.deleteKvStore()Logger.info(TAG, `aboutToDisappear end`)};build() {Column() {Blank().width('100%').height(72)Text(this.title).width('100%').fontSize(28).margin({ top: '10%' }).fontColor(Color.White).textAlign(TextAlign.Center)Image(this.albumSrc).width(this.isLand ? '60%' : '89%').objectFit(ImageFit.Contain).margin({ top: 50, left: 40, right: 40 })Row() {Text(this.currentTimeText).fontSize(20).fontColor(Color.White)Blank()Text(this.totalTimeText).fontSize(20).fontColor(Color.White)}.width('90%').margin({ top: '12%' })Slider({ value: typeof (this.currentProgress) === 'number' ? this.currentProgress : 0 }).trackColor('#64CCE7FF').width('90%').selectedColor('#ff0c4ae7').onChange((value: number, mode: SliderChangeMode) => {this.currentProgress = value;if (typeof (this.totalMs) !== 'number') {this.currentProgress = 0;Logger.info(TAG, `setProgress ignored, totalMs= ${this.totalMs}`);return;};let currentMs = this.currentProgress / ONE_HUNDRED * this.totalMs;this.currentTimeText = this.getShownTimer(currentMs);if (mode === SliderChangeMode.End || mode === 3) {Logger.info(TAG, `player.seek= ${currentMs}`);PlayerModel.seek(currentMs);};})Row() {ForEach(this.imageArrays, (item: Resource, index: number | undefined) => {Column() {Image(item).size({ width: 74, height: 74 }).objectFit(ImageFit.Contain).onClick(() => {switch (index) {case 0:this.onAppSharedClick();break;case 1:this.onPreviousClick();break;case 2:this.onPlayClick();break;case 3:this.onNextClick();break;default:break;}})}.id('image' + (index !== undefined ? (index + 1) : 0)).width(100).height(100).alignItems(HorizontalAlign.Center).justifyContent(FlexAlign.Center)})}.width('100%').margin({ top: '4%' }).justifyContent(FlexAlign.SpaceEvenly)}.width('100%').height('100%').backgroundImage($r('app.media.bg_blurry')).backgroundImageSize({ width: '100%', height: '100%' })}}
分布式数据管理

(1) 管理分布式数据库
创建一个KVManager对象实例,用于管理分布式数据库对象。通过distributedData.createKVManager(config),并通过指定Options和storeId,创建并获取KVStore数据库,并通过Promise方式返回,此方法为异步方法,例如this.kvManager.getKVStore(STORE_ID, options).then((store) => {})
(2) 订阅分布式数据变化
通过订阅分布式数据库所有(本地及远端)数据变化实现数据协同[源码参考]。

/** Copyright (c) 2022-2023 Huawei Device Co., Ltd.* Licensed under the Apache License, Version 2.0 (the "License");* you may not use this file except in compliance with the License.* You may obtain a copy of the License at**     http://www.apache.org/licenses/LICENSE-2.0** Unless required by applicable law or agreed to in writing, software* distributed under the License is distributed on an "AS IS" BASIS,* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.* See the License for the specific language governing permissions and* limitations under the License.*/import abilityAccessCtrl, { Permissions } from '@ohos.abilityAccessCtrl';import display from '@ohos.display';import common from '@ohos.app.ability.common';import mediaQuery from '@ohos.mediaquery';import rpc from '@ohos.rpc';import Want from '@ohos.app.ability.Want';import PermissionRequestResult from 'security/PermissionRequestResult';import KvStoreModel from '../model/KvStoreModel';import Logger from '../model/Logger';import PlayerModel from '../model/PlayerModel';import deviceManager from '@ohos.distributedDeviceManager';import ability from '@ohos.ability.ability';import { RemoteDeviceModel } from '../model/RemoteDeviceModel';import { DeviceDialog } from '../common/DeviceDialog';import {APPLICATION_BUNDLE_NAME,APPLICATION_SERVICE_NAME,MusicSharedEventCode,MusicSharedStatus,MusicConnectEvent} from '../common/MusicSharedDefinition';const TAG: string = 'Index';const DESIGN_WIDTH: number = 720.0;const SYSTEM_UI_HEIGHT: number = 134;const DESIGN_RATIO: number = 16 / 9;const ONE_HUNDRED: number = 100;const ONE_THOUSAND: number = 1000;const SIXTY: number = 60;const REMOTE_ABILITY_STARTED: string = 'remoteAbilityStarted';const ABILITY_SHARED_BUTTON = 0;const DEFAULT_NUM = -1;const PREVIOUS_CLICK = 2;interface Params {uri: string,seekTo: number,isPlaying: boolean};@Entry@Componentstruct Index {private listener = mediaQuery.matchMediaSync('screen and (min-aspect-ratio: 1.5) or (orientation: landscape)');@State isLand: boolean = false;@State currentTimeText: string = '';@State currentProgress: number = 0;@State totalMs: number = 0;@State riscale: number = 1;@State risw: number = 720;@State rish: number = 1280;@State isSwitching: boolean = false;@State deviceLists: Array<deviceManager.DeviceBasicInfo> = [];@State isDialogShowing: boolean = false;@State isDistributed: boolean = false;@State title: string = '';@State totalTimeText: string = '00:00';@State albumSrc: Resource = $r('app.media.album');@State selectedIndex: number = 0;@State imageArrays: Array<Resource> = [$r('app.media.ic_hop'), $r('app.media.ic_play_previous'), $r('app.media.ic_play'), $r('app.media.ic_play_next')];private dialogController: CustomDialogController | null = null;@StorageLink('exitMusicApp') @Watch('exitMusicApp') isExitMusicApp: boolean = false;@StorageLink('remoteServiceExtensionConnectEvent') @Watch('remoteServiceExtensionConnectEvent') isRemoteServiceExtensionConnectEvent: boolean = false;@StorageLink('musicPlay') @Watch('musicPlay') isMusicPlay: boolean = false;@StorageLink('musicPause') @Watch('musicPause') isMusicPause: boolean = false;private remoteDeviceModel: RemoteDeviceModel = new RemoteDeviceModel();private context: common.UIAbilityContext | null = null;private deviceId: string | null = null;private clickFlag = MusicSharedStatus.MUSIC_SHARED;private localExtensionRemote: rpc.IRemoteObject | null = null;onLand = (mediaQueryResult: mediaQuery.MediaQueryResult) => {Logger.info(TAG, `onLand: mediaQueryResult.matches= ${mediaQueryResult.matches}`);if (mediaQueryResult.matches) {this.isLand = true;} else {this.isLand = false;};};showDialog() {this.remoteDeviceModel.registerDeviceListCallback(() => {Logger.info(TAG, 'registerDeviceListCallback, callback entered');this.deviceLists = [];this.deviceLists.push({deviceId: '0',deviceName: 'local device',deviceType: '0',networkId: ''});let deviceTempList = this.remoteDeviceModel.discoverLists.length > 0 ? this.remoteDeviceModel.discoverLists : this.remoteDeviceModel.deviceLists;for (let i = 0; i < deviceTempList.length; i++) {Logger.info(TAG, `device ${i}/${deviceTempList.length} deviceId= ${deviceTempList[i].deviceId},deviceName= ${deviceTempList[i].deviceName}, deviceType= ${deviceTempList[i].deviceType}`);this.deviceLists.push(deviceTempList[i]);Logger.info(TAG, 'deviceLists push end');};Logger.info(TAG, 'CustomDialogController start');if (this.dialogController !== null) {this.dialogController.close();this.dialogController = null;}this.dialogController = new CustomDialogController({builder: DeviceDialog({deviceLists: this.deviceLists,selectedIndex: this.selectedIndex,selectedIndexChange: this.selectedIndexChange}),autoCancel: true,customStyle: true});this.dialogController.open();Logger.info(TAG, 'CustomDialogController end');})};showPromptDialog(title: ResourceStr, str: ResourceStr) {AlertDialog.show({title: title,message: str,confirm: {value: $r('app.string.cancel'),action: () => {Logger.info(TAG, `Button-clicking callback`);}},cancel: () => {Logger.info(TAG, `Closed callbacks`);}});};remoteServiceExtensionConnectEvent(event: string) {if (typeof (event) === 'string') {let viewThis = AppStorage.get<Index>('viewThis');if (viewThis !== undefined) {if (event === MusicConnectEvent.EVENT_CONNECT) {viewThis.clickFlag = MusicSharedStatus.MUSIC_STOP_SHARED;viewThis.imageArrays[ABILITY_SHARED_BUTTON] = $r('app.media.ic_hop');Logger.info(TAG, 'remote service on connect callbacked');} else if (event === MusicConnectEvent.EVENT_DISCONNECT) {viewThis.imageArrays[ABILITY_SHARED_BUTTON] = $r('app.media.ic_hop');viewThis.clickFlag = MusicSharedStatus.MUSIC_SHARED;viewThis.showPromptDialog($r('app.string.ConnectRemoteDevices'), $r('app.string.onDisconnectService'));} else if (event === MusicConnectEvent.EVENT_FAILED) {viewThis.imageArrays[ABILITY_SHARED_BUTTON] = $r('app.media.ic_hop');viewThis.clickFlag = MusicSharedStatus.MUSIC_SHARED;viewThis.showPromptDialog($r('app.string.ConnectRemoteDevices'), $r('app.string.onFailedService'));} else if (event === MusicConnectEvent.EVENT_TIMEOUT) {this.imageArrays[ABILITY_SHARED_BUTTON] = $r('app.media.ic_hop');viewThis.clickFlag = MusicSharedStatus.MUSIC_SHARED;viewThis.showPromptDialog($r('app.string.ConnectRemoteDevices'), $r('app.string.ConnectionTimeout'));}}} else {Logger.info(TAG, 'event is not a string');};};musicPause() {Logger.info(TAG, 'music pause recv');PlayerModel.pause();let viewThis = AppStorage.get<Index>('viewThis');viewThis!.imageArrays[PREVIOUS_CLICK] = $r('app.media.ic_play');};musicPlay() {Logger.info(TAG, 'music play recv');PlayerModel.play(DEFAULT_NUM, true);let viewThis = AppStorage.get<Index>('viewThis');viewThis!.imageArrays[PREVIOUS_CLICK] = $r('app.media.ic_pause');};exitMusicApp() {Logger.info(TAG, `exit music app called`);if (this.localExtensionRemote !== null && typeof (this.localExtensionRemote) === 'object') {let option = new rpc.MessageOption();let data = new rpc.MessageParcel();let reply = new rpc.MessageParcel();this.localExtensionRemote.sendRequest(MusicSharedEventCode.STOP_LOCAL_SERIVCE,data,reply,option);} else {Logger.info(TAG, `Remote start type is error or deviceID is empty, typeof= ${typeof (this.localExtensionRemote)}`);};};connectLocalExtension() {let localServiceWant: Want = {bundleName: APPLICATION_BUNDLE_NAME,abilityName: APPLICATION_SERVICE_NAME,};let connectOptions: ability.ConnectOptions = {onConnect: (elementName, remote) => {this.localExtensionRemote = remote;Logger.info(TAG, `onConnect called elementName is ${JSON.stringify(elementName)}`);},onDisconnect: (elementName) => {if (this.context !== null) {this.context.terminateSelf();Logger.info(TAG, `OnDisconnect called elementName is ${JSON.stringify(elementName)}`);};},onFailed: (code) => {if (this.context !== null) {this.context.terminateSelf();Logger.info(TAG, `OnFailed called code is ${JSON.stringify(code)}`);}}};if (this.context !== null) {this.context.connectServiceExtensionAbility(localServiceWant, connectOptions);};};startRemoteExtension(deviceId: string, params: object) {if (this.localExtensionRemote !== null && typeof (this.localExtensionRemote) === 'object' && typeof (deviceId) === 'string' && deviceId !== '') {let option = new rpc.MessageOption();let data = new rpc.MessageParcel();let reply = new rpc.MessageParcel();data.writeString(deviceId);data.writeString(JSON.stringify(params));this.localExtensionRemote.sendRequest(MusicSharedEventCode.START_DISTRIBUTED_MUSIC_SERVICE, data, reply, option);this.deviceId = deviceId;this.imageArrays[ABILITY_SHARED_BUTTON] = $r('app.media.ic_hop');} else {Logger.info(TAG, `Remote start type is error or deviceID is empty, typeof= ${typeof (this.localExtensionRemote)}`);};};stopRemoteExtension() {if (this.localExtensionRemote !== null && typeof (this.localExtensionRemote) === 'object' && typeof (this.deviceId) === 'string' && this.deviceId !== '') {let option = new rpc.MessageOption();let data = new rpc.MessageParcel();let reply = new rpc.MessageParcel();data.writeString(this.deviceId);this.localExtensionRemote.sendRequest(MusicSharedEventCode.STOP_DISTRIBUTED_MUSIC_SERVICE, data, reply, option);this.deviceId = '';} else {Logger.info(TAG, `Remote stopped type is wrong or deviceID is empty, typeof= ${typeof (this.localExtensionRemote)}`);};};sendMessagePlay() {if (this.localExtensionRemote !== null) {let option = new rpc.MessageOption();let data = new rpc.MessageParcel();let reply = new rpc.MessageParcel();this.localExtensionRemote.sendRequest(MusicSharedEventCode.PLAY_MUSIC_SERVICE, data, reply, option);Logger.info(TAG, `onPlayClick send mssage success`);} else {Logger.info(TAG, `can not get proxy`);return;};};sendMessagePause() {if (this.localExtensionRemote === null) {Logger.info(TAG, `can not get proxy`);return;};let option = new rpc.MessageOption();let data = new rpc.MessageParcel();let reply = new rpc.MessageParcel();this.localExtensionRemote.sendRequest(MusicSharedEventCode.PAUSE_MUSIC_SERVICE, data, reply, option);Logger.info(TAG, `onPauseClick send mssage success`);};onBackPress() {if (this.isDialogShowing === true) {this.dismissDialog();return true;};return false;};onPageHide() {if (this.isDialogShowing === true) {this.dismissDialog();return true;};return false;};dismissDialog() {if (this.dialogController !== null) {this.dialogController.close();}this.remoteDeviceModel.unregisterDeviceListCallback();this.isDialogShowing = false;};startAbilityContinuation(deviceId: string) {let params: Params = {uri: '',seekTo: 0,isPlaying: false};Logger.info(TAG, `startAbilityContinuation PlayerModel.index= ${PlayerModel.index}/${PlayerModel.playlist.audioFiles.length}`);if (PlayerModel.index >= 0 && PlayerModel.index <= PlayerModel.playlist.audioFiles.length) {params = {uri: PlayerModel.playlist.audioFiles[PlayerModel.index].fileUri,seekTo: PlayerModel.getCurrentMs(),isPlaying: PlayerModel.isPlaying};};Logger.info(TAG, `context.startAbility deviceId= ${deviceId}`);if (this.context !== null) {KvStoreModel.setOnMessageReceivedListener(this.context, REMOTE_ABILITY_STARTED, () => {Logger.info(TAG, 'OnMessageReceived, terminateSelf');});};Logger.info(TAG, `context.startAbility start`);this.clickFlag = MusicSharedStatus.MUSIC_REMOTING;this.startRemoteExtension(deviceId, params);this.clearSelectState();Logger.info(TAG, 'context.startAbility end');};selectedIndexChange = (selectedIndex: number) => {if (this.context !== null && selectedIndex === 0) {this.context.startAbility({ bundleName: 'ohos.samples.distributedmusicplayer',abilityName: 'ohos.samples.distributedmusicplayer.MainAbility',deviceId: this.deviceLists[selectedIndex].deviceId,parameters: {isFA: 'EXIT'}}).then(() => {Logger.info(TAG, `startAbility finished`);}).catch((err: Error) => {Logger.info(TAG, `startAbility filed error = ${JSON.stringify(err)}`);});this.isDistributed = false;this.selectedIndex = 0;if (this.dialogController !== null) {this.dialogController.close();}this.deviceLists = [];return;};this.selectedIndex = selectedIndex;this.selectDevice();};selectDevice() {Logger.info(TAG, 'start ability ......');if (this.selectedIndex !== undefined && (this.remoteDeviceModel === null || this.remoteDeviceModel.discoverLists.length <= 0)) {Logger.info(TAG, `start ability device:${JSON.stringify(this.deviceLists)}`);this.startAbilityContinuation(this.deviceLists[this.selectedIndex].networkId as string);this.clearSelectState();return;};Logger.info(TAG, 'start ability, needAuth');if (this.selectedIndex !== undefined){this.remoteDeviceModel.authDevice(this.deviceLists[this.selectedIndex], (device: deviceManager.DeviceBasicInfo) => {Logger.info(TAG, 'auth and online finished');this.startAbilityContinuation(device.networkId);});}Logger.info(TAG, 'start ability2 ......');this.clearSelectState();};clearSelectState() {this.deviceLists = [];if (this.dialogController) {this.dialogController.close();this.dialogController = null;};};getShownTimer(ms: number) {let minStr: string;let secStr: string;let seconds = Math.floor(ms / ONE_THOUSAND);let sec = seconds % SIXTY;Logger.info(TAG, `getShownTimer sec = ${sec}`);let min = (seconds - sec) / SIXTY;Logger.info(TAG, `getShownTimer min = ${min}`);if (sec < 10) {secStr = '0' + sec;} else {secStr = sec.toString(10);};if (min < 10) {minStr = '0' + min;} else {minStr = min.toString(10);};Logger.warn(TAG, `getShownTimer = ${minStr}:${secStr}`);return minStr + ':' + secStr;};refreshSongInfo(index: number) {Logger.info(TAG, `refreshSongInfo ${index}/${PlayerModel.playlist.audioFiles.length}`);if (index >= PlayerModel.playlist.audioFiles.length) {Logger.warn(TAG, 'refreshSongInfo ignored');return;};// update song titlethis.title = PlayerModel.playlist.audioFiles[index].name;this.albumSrc = (index % 2 === 0) ? $r('app.media.album') : $r('app.media.album2');// update durationthis.totalMs = PlayerModel.getDuration();this.totalTimeText = this.getShownTimer(this.totalMs);this.currentTimeText = this.getShownTimer(PlayerModel.getCurrentMs());Logger.info(TAG, `refreshSongInfo this.title= ${this.title}, this.totalMs= ${this.totalMs}, this.totalTimeText= ${this.totalTimeText},this.currentTimeText= ${this.currentTimeText}`);};onAppSharedClick() {if (this.clickFlag === MusicSharedStatus.MUSIC_SHARED) {Logger.info(TAG, `1start button is ${JSON.stringify(this.imageArrays[ABILITY_SHARED_BUTTON])}`);this.showDialog();} else if (this.clickFlag === MusicSharedStatus.MUSIC_STOP_SHARED) {Logger.info(TAG, `2start button is ${JSON.stringify(this.imageArrays[ABILITY_SHARED_BUTTON])}`);this.stopRemoteExtension();this.imageArrays[ABILITY_SHARED_BUTTON] = $r('app.media.ic_hop');};};onPreviousClick() {if (this.isSwitching) {Logger.info(TAG, 'onPreviousClick ignored, isSwitching');return;};Logger.info(TAG, 'onPreviousClick');PlayerModel.index--;if (PlayerModel.index < 0 && PlayerModel.playlist.audioFiles.length >= 1) {PlayerModel.index = PlayerModel.playlist.audioFiles.length - 1;};this.currentProgress = 0;this.isSwitching = true;PlayerModel.preLoad(PlayerModel.index, () => {this.refreshSongInfo(PlayerModel.index);PlayerModel.play(0, true);if (PlayerModel.isPlaying) {this.imageArrays[PREVIOUS_CLICK] = $r('app.media.ic_pause');};this.isSwitching = false;});};onNextClick() {if (this.isSwitching) {Logger.info(TAG, 'onNextClick ignored, isSwitching');return;};Logger.info(TAG, 'onNextClick');PlayerModel.index++;if (PlayerModel.index >= PlayerModel.playlist.audioFiles.length) {PlayerModel.index = 0;};this.currentProgress = 0;this.isSwitching = true;PlayerModel.preLoad(PlayerModel.index, () => {this.refreshSongInfo(PlayerModel.index);PlayerModel.play(0, true);if (PlayerModel.isPlaying) {this.imageArrays[PREVIOUS_CLICK] = $r('app.media.ic_pause');};this.isSwitching = false;});};onPlayClick() {if (this.isSwitching) {Logger.info(TAG, 'onPlayClick ignored, isSwitching');return;};Logger.info(TAG, `onPlayClick isPlaying= ${PlayerModel.isPlaying}`);if (PlayerModel.isPlaying) {PlayerModel.pause();this.imageArrays[PREVIOUS_CLICK] = $r('app.media.ic_play');this.sendMessagePause();} else {PlayerModel.preLoad(PlayerModel.index, () => {PlayerModel.play(DEFAULT_NUM, true);this.imageArrays[PREVIOUS_CLICK] = $r('app.media.ic_pause');this.sendMessagePlay();})};};restoreFromWant() {Logger.info(TAG, 'restoreFromWant');let status: Record<string, Object> | undefined = AppStorage.get('status');if (status !== undefined && status !== null && status.uri !== null) {KvStoreModel.broadcastMessage(this.context, REMOTE_ABILITY_STARTED);Logger.info(TAG, 'restorePlayingStatus');PlayerModel.restorePlayingStatus(status, (index: number) => {Logger.info(TAG, `restorePlayingStatus finished, index= ${index}`);if (index >= 0) {this.refreshSongInfo(index);} else {PlayerModel.preLoad(0, () => {this.refreshSongInfo(0);})}if (status !== undefined) {Logger.info(TAG, `Index PlayerModel.restorePlayingStatus this.totalMs = ${this.totalMs}, status.seekTo = ${status.seekTo}`);this.currentProgress = Math.floor(Number(status.seekTo) / this.totalMs * ONE_HUNDRED);}})} else {PlayerModel.preLoad(0, () => {this.refreshSongInfo(0);});}};aboutToAppear() {Logger.info(TAG, `begin`);Logger.info(TAG, 'grantPermission');this.context = getContext(this) as common.UIAbilityContext;let atManager: abilityAccessCtrl.AtManager = abilityAccessCtrl.createAtManager();let permission: Array<Permissions> = ['ohos.permission.DISTRIBUTED_DATASYNC'];try {atManager.requestPermissionsFromUser(this.context, permission).then((data: PermissionRequestResult) => {Logger.info(TAG, `data: ${JSON.stringify(data)}`);}).catch((err: object) => {Logger.info(TAG, `err: ${JSON.stringify(err)}`);})} catch (err) {Logger.info(TAG, `catch err->${JSON.stringify(err)}`);}display.getDefaultDisplay().then((dis: display.Display) => {Logger.info(TAG, `getDefaultDisplay dis= ${JSON.stringify(dis)}`);let proportion = DESIGN_WIDTH / dis.width;let screenWidth = DESIGN_WIDTH;let screenHeight = (dis.height - SYSTEM_UI_HEIGHT) * proportion;this.riscale = (screenHeight / screenWidth) / DESIGN_RATIO;if (this.riscale < 1) {// The screen ratio is shorter than design ratiothis.risw = screenWidth * this.riscale;this.rish = screenHeight;} else {// The screen ratio is longer than design ratiothis.risw = screenWidth;this.rish = screenHeight / this.riscale;}Logger.info(TAG, `proportion=${proportion} , screenWidth= ${screenWidth},screenHeight= ${screenHeight} , riscale= ${this.riscale} , risw= ${this.risw} , rish= ${this.rish}`);})Logger.info(TAG, 'getDefaultDisplay end');this.currentTimeText = this.getShownTimer(0);PlayerModel.setOnStatusChangedListener((isPlaying: string) => {Logger.info(TAG, `on player status changed, isPlaying= ${isPlaying} refresh ui`);PlayerModel.setOnPlayingProgressListener((currentTimeMs: number) => {this.currentTimeText = this.getShownTimer(currentTimeMs);this.currentProgress = Math.floor(currentTimeMs / this.totalMs * ONE_HUNDRED);});if (isPlaying) {this.imageArrays[PREVIOUS_CLICK] = $r('app.media.ic_pause');} else {this.imageArrays[PREVIOUS_CLICK] = $r('app.media.ic_play');}});PlayerModel.getPlaylist(() => {Logger.info(TAG, 'on playlist generated, refresh ui');this.restoreFromWant();});AppStorage.setOrCreate('viewThis', this);this.connectLocalExtension();};aboutToDisappear() {Logger.info(TAG, `aboutToDisappear begin`)if (PlayerModel === undefined) {return}PlayerModel.release()this.remoteDeviceModel.unregisterDeviceListCallback()this.dialogController = nullKvStoreModel.deleteKvStore()Logger.info(TAG, `aboutToDisappear end`)};build() {Column() {Blank().width('100%').height(72)Text(this.title).width('100%').fontSize(28).margin({ top: '10%' }).fontColor(Color.White).textAlign(TextAlign.Center)Image(this.albumSrc).width(this.isLand ? '60%' : '89%').objectFit(ImageFit.Contain).margin({ top: 50, left: 40, right: 40 })Row() {Text(this.currentTimeText).fontSize(20).fontColor(Color.White)Blank()Text(this.totalTimeText).fontSize(20).fontColor(Color.White)}.width('90%').margin({ top: '12%' })Slider({ value: typeof (this.currentProgress) === 'number' ? this.currentProgress : 0 }).trackColor('#64CCE7FF').width('90%').selectedColor('#ff0c4ae7').onChange((value: number, mode: SliderChangeMode) => {this.currentProgress = value;if (typeof (this.totalMs) !== 'number') {this.currentProgress = 0;Logger.info(TAG, `setProgress ignored, totalMs= ${this.totalMs}`);return;};let currentMs = this.currentProgress / ONE_HUNDRED * this.totalMs;this.currentTimeText = this.getShownTimer(currentMs);if (mode === SliderChangeMode.End || mode === 3) {Logger.info(TAG, `player.seek= ${currentMs}`);PlayerModel.seek(currentMs);};})Row() {ForEach(this.imageArrays, (item: Resource, index: number | undefined) => {Column() {Image(item).size({ width: 74, height: 74 }).objectFit(ImageFit.Contain).onClick(() => {switch (index) {case 0:this.onAppSharedClick();break;case 1:this.onPreviousClick();break;case 2:this.onPlayClick();break;case 3:this.onNextClick();break;default:break;}})}.id('image' + (index !== undefined ? (index + 1) : 0)).width(100).height(100).alignItems(HorizontalAlign.Center).justifyContent(FlexAlign.Center)})}.width('100%').margin({ top: '4%' }).justifyContent(FlexAlign.SpaceEvenly)}.width('100%').height('100%').backgroundImage($r('app.media.bg_blurry')).backgroundImageSize({ width: '100%', height: '100%' })}}
跨设备播放操作

(1)分布式设备管理器绑定应用包 deviceManager.createDeviceManager(‘ohos.samples.distributedmusicplayer’) [源码参考]。

/** Copyright (c) 2022 Huawei Device Co., Ltd.* Licensed under the Apache License, Version 2.0 (the "License");* you may not use this file except in compliance with the License.* You may obtain a copy of the License at**     http://www.apache.org/licenses/LICENSE-2.0** Unless required by applicable law or agreed to in writing, software* distributed under the License is distributed on an "AS IS" BASIS,* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.* See the License for the specific language governing permissions and* limitations under the License.*/import deviceManager from '@ohos.distributedDeviceManager';import Logger from '../model/Logger';let SUBSCRIBE_ID: number = 100;const RANDOM: number = 65536;const TAG: string = 'RemoteDeviceModel';export class RemoteDeviceModel {public deviceLists: Array<deviceManager.DeviceBasicInfo> = [];public discoverLists: Array<deviceManager.DeviceBasicInfo> = [];private callback: () => void = null;private authCallback: () => void = null;private deviceManager: deviceManager.DeviceManager = undefined;registerDeviceListCallback(callback) {if (typeof (this.deviceManager) === 'undefined') {Logger.info(TAG, 'deviceManager.createDeviceManager begin');try {this.deviceManager = deviceManager.createDeviceManager('ohos.samples.distributedmusicplayer');this.registerDeviceList(callback);Logger.info(TAG, `createDeviceManager callback returned, value= ${JSON.stringify(this.deviceManager)}`);} catch (error) {Logger.info(TAG, `createDeviceManager throw error, error=${error} message=${error.message}`);}Logger.info(TAG, 'deviceManager.createDeviceManager end');} else {this.registerDeviceList(callback);};};registerDeviceList(callback) {Logger.info(TAG, 'registerDeviceListCallback');this.callback = callback;if (this.deviceManager === undefined) {Logger.error(TAG, 'deviceManager has not initialized');this.callback();return;};Logger.info(TAG, 'getTrustedDeviceListSync begin');let list: deviceManager.DeviceBasicInfo[] = [];try {list = this.deviceManager.getAvailableDeviceListSync();} catch (error) {Logger.info(TAG, `getTrustedDeviceListSync throw error, error=${error} message=${error.message}`);};Logger.info(TAG, `getTrustedDeviceListSync end, deviceLists= ${JSON.stringify(list)}`);if (typeof (list) !== 'undefined' && typeof (list.length) !== 'undefined') {this.deviceLists = list;};this.callback();Logger.info(TAG, 'callback finished');try {this.deviceManager.on('deviceStateChange', (data) => {Logger.info(TAG, `deviceStateChange data= ${JSON.stringify(data)}`);switch (data.action) {case deviceManager.DeviceStateChange.AVAILABLE:this.discoverLists = [];this.deviceLists.push(data.device);Logger.info(TAG, `reday, updated device list= ${JSON.stringify(this.deviceLists)} `);let list: deviceManager.DeviceBasicInfo[] = [];try {list = this.deviceManager.getAvailableDeviceListSync();} catch (err) {Logger.info(TAG, `this err is ${JSON.stringify(err)}`);}Logger.info(TAG, `getTrustedDeviceListSync end, deviceList= ${JSON.stringify(list)}`);if (typeof (list) !== 'undefined' && typeof (list.length) !== 'undefined') {this.deviceLists = list;}this.callback();break;case deviceManager.DeviceStateChange.UNAVAILABLE:if (this.deviceLists.length > 0) {let list = [];for (let i = 0; i < this.deviceLists.length; i++) {if (this.deviceLists[i].deviceId !== data.device.deviceId) {list[i] = data.device;};};this.deviceLists = list;};Logger.info(TAG, `offline, updated device list= ${JSON.stringify(this.deviceLists)}`);this.callback();break;default:break;};});this.deviceManager.on('discoverSuccess', (data) => {Logger.info(TAG, `discoverSuccess data= ${JSON.stringify(data)}`);Logger.info(TAG, `discoverSuccess this.deviceLists= ${this.deviceLists}, this.deviceLists.length= ${this.deviceLists.length}`);for (let i = 0;i < this.discoverLists.length; i++) {if (this.discoverLists[i].deviceId === data.device.deviceId) {Logger.info(TAG, 'device founded, ignored');return;};};this.discoverLists[this.discoverLists.length] = data.device;this.callback();});this.deviceManager.on('discoverFailure', (data) => {Logger.info(TAG, `discoverFailure data= ${JSON.stringify(data)}`);});this.deviceManager.on('serviceDie', () => {Logger.error(TAG, 'serviceDie');});} catch (error) {Logger.info(TAG, `on throw error, error=${error} message=${error.message}`);}let discoverParam = {'discoverTargetType': 1};let filterOptions = {'availableStatus': 0};Logger.info(TAG, `startDiscovering ${SUBSCRIBE_ID}`);try {if (this.deviceManager !== null) {this.deviceManager.startDiscovering(discoverParam, filterOptions);};} catch (error) {Logger.error(TAG, `startDiscovering throw error, error=${error} message=${error.message}`);};};authDevice(device, callback) {Logger.info(TAG, `authDevice ${device}`);if (device !== undefined) {for (let i = 0; i < this.discoverLists.length; i++) {if (this.discoverLists[i].deviceId === device.deviceId) {Logger.info(TAG, 'device founded, ignored');let bindParam = {bindType: 1,targetPkgName: 'ohos.samples.distributedmusicplayer',appName: 'Music',};Logger.info(TAG, `authenticateDevice ${JSON.stringify(this.discoverLists[i])}`);try {this.deviceManager.bindTarget(device.deviceId, bindParam, (err, data) => {if (err) {Logger.error(TAG, `authenticateDevice error: ${JSON.stringify(err)}`);this.authCallback = () => {};return;};Logger.info(TAG, `authenticateDevice succeed, data= ${JSON.stringify(data)}`);this.authCallback = callback;});} catch (error) {Logger.error(TAG, `authenticateDevice throw error, error=${JSON.stringify(error)} message=${error.message}`);}}}}};unregisterDeviceListCallback() {Logger.info(TAG, `stopDiscovering ${SUBSCRIBE_ID}`);if (this.deviceManager === undefined) {return;};try {this.deviceManager.stopDiscovering();this.deviceManager.off('deviceStateChange');this.deviceManager.off('discoverSuccess');this.deviceManager.off('discoverFailure');this.deviceManager.off('serviceDie');} catch (error) {Logger.info(TAG, `stopDeviceDiscovery throw error, error=${error} message=${error.message}`);}this.deviceLists = [];};}

(2) 初始化播放器 构造函数中通过’@ohos.multimedia.media’组件对播放器进行实例化,并调用播放器初始化函数,通过播放器的on函数,监听error、finish、timeUpdate
(3) 同步当前播放数据 播放器通过调用selectedIndexChange(),将当前播放的资源、时间、以及播放状态同步给选中的设备。
(4) 接收当前播放数据 播放器通过在aboutToAppear()时调用this.restoreFromWant(), KvStoreModel组件获取播放列表,playerModel组件重新加载播放器状态和资源。

http://www.15wanjia.com/news/17713.html

相关文章:

  • 玉环做企业网站佛山做网络优化的公司
  • 做会员卡的网站在线cpc广告点击日结联盟
  • 如何用网站做课件seo综合查询工具有什么功能
  • 手机模板网站生成制作软件线上营销活动案例
  • 没有后台的网站怎么做排名百度云资源搜索平台
  • 网站的黄金看盘软件aso优化排名违法吗
  • www开头网站怎么做东莞谷歌推广公司
  • o2o网站建设咨询温州seo结算
  • 南京网站设南京网站设计计做百度seo
  • 建个大型网站要多少钱百度客服电话人工服务热线电话
  • 自己做的网站显示不出来推客平台
  • 个人资料库网站怎么做百度seo学院
  • 网站备案域名还是空间百度云搜索引擎入口百度网盘
  • 武汉做网站公司hlbzx谷歌外贸网站推广
  • 深圳网络建设网站手机网页制作
  • 企业英文网站百度学术免费查重入口
  • php网站建设模板下载seo全网图文推广
  • wordpress建博客网站吗怎么投放网络广告
  • 重庆网网站建设公司网站优化招聘
  • 关键词广告北京外包seo公司
  • 沈阳网页设计招聘seo关键词排名优化官网
  • wordpress个人下载网站模板下载培训班招生方案有哪些
  • 青岛的做网站公司齐三seo顾问
  • 临淄网站制作补肾壮阳吃什么药效果好
  • 做简易网站的APP成品网站建站空间
  • wordpress 首页欢迎站长seo综合查询
  • 静态网站开发 内容seo推广软件怎样
  • 网站开发线上销售技巧百度竞价排名公式
  • 建网站首选公司新闻媒体发稿平台
  • 安徽省公共资源交易中心网站引流推广