鸿蒙HarmonyOS——AVSession开发指导

news2024/12/25 9:10:13

AVSession开发指导

说明:

AVSession的所有接口均为系统接口,其功能仅提供给系统应用使用。

会话接入端开发指导

基本概念

  • 会话元数据'AVMetadata': 媒体数据相关属性,包含标识当前媒体的ID(assetId),上一首媒体的ID(previousAssetId),下一首媒体的ID(nextAssetId),标题(title),专辑作者(author),专辑名称(album),词作者(writer),媒体时长(duration)等属性。
  • 会话描述符'AVSessionDescriptor': 描述媒体会话的相关信息。包含标识会话的ID(sessionId),会话的类型type(音频Audio/视频Video),会话自定义名称(sessionTag),会话所属应用的信息(elementName)等。
  • 媒体播放状态'AVPlaybackState':用于描述媒体播放状态的相关属性。包含当前媒体的播放状态(state)、位置(position)、速度(speed)、缓冲时间(bufferedTime)、循环模式(loopMode)、是否收藏(isFavorite)等属性。

接口说明

会话接入端常用接口如下表所示。接口返回值有两种返回形式:callback和promise,下表中为callback形式接口,promise和callback只是返回值方式不一样,功能相同。更多API说明请参见API文档。

表1:会话接入端常用接口

接口名描述
createAVSession(context: Context, tag: string, type: AVSessionType, callback: AsyncCallback): void创建会话
setAVMetadata(data: AVMetadata, callback: AsyncCallback): void设置会话元数据
setAVPlaybackState(state: AVPlaybackState, callback: AsyncCallback): void设置会话播放状态信息
setLaunchAbility(ability: WantAgent, callback: AsyncCallback): void设置启动ability
getController(callback: AsyncCallback): void获取当前会话自身控制器
getOutputDevice(callback: AsyncCallback): void获取音频输出设备信息
activate(callback: AsyncCallback): void激活会话
destroy(callback: AsyncCallback): void销毁会话

开发步骤

1.导入模块接口

import avSession from '@ohos.multimedia.avsession';
import wantAgent from '@ohos.app.ability.wantAgent';
import featureAbility from '@ohos.ability.featureAbility';

2.创建会话并激活会话

// 全局变量定义
let mediaFavorite = false;
let currentSession = null;
let context = featureAbility.getContext();

// 创建音频类型会话
avSession.createAVSession(context, "AudioAppSample", 'audio').then((session) => {
   currentSession = session;
   currentSession.activate();  // 激活会话
}).catch((err) => {
   console.info(`createAVSession : ERROR : ${err.message}`);
});

3.设置AVSession会话信息,包括: - 设置会话元数据,除了媒体ID必选外,可选设置媒体标题、专辑信息、媒体作者、媒体时长、上一首/下一首媒体ID等。详细的会话元数据信息可参考API文档中的AVMetadata。 - 设置启动Ability,通过WantAgent的接口实现。WantAgent一般用于封装行为意图信息。 - 设置播放状态。

// 设置会话元数据
let metadata  = {
   assetId: "121278",
   title: "lose yourself",
   artist: "Eminem",
   author: "ST",
   album: "Slim shady",
   writer: "ST",
   composer: "ST",
   duration: 2222,
   mediaImage: "https://www.example.com/example.jpg",       // 请开发者根据实际情况使用
   subtitle: "8 Mile",
   description: "Rap",
   lyric: "https://www.example.com/example.lrc",            // 请开发者根据实际情况使用
   previousAssetId: "121277",
   nextAssetId: "121279",
};
currentSession.setAVMetadata(metadata).then(() => {
   console.info('setAVMetadata successfully');
}).catch((err) => {
   console.info(`setAVMetadata : ERROR : ${err.message}`);
});

// 设置启动ability
let wantAgentInfo = {
  wants: [
    {
      bundleName: "com.neu.setResultOnAbilityResultTest1",
      abilityName: "com.example.test.EntryAbility",
    }
  ],
  operationType: wantAgent.OperationType.START_ABILITIES,
  requestCode: 0,
  wantAgentFlags:[wantAgent.WantAgentFlags.UPDATE_PRESENT_FLAG]
}

wantAgent.getWantAgent(wantAgentInfo).then((agent) => {
  currentSession.setLaunchAbility(agent).then(() => {
    console.info('setLaunchAbility successfully');
  }).catch((err) => {
    console.info(`setLaunchAbility : ERROR : ${err.message}`);
  });
});

// 设置播放状态
let PlaybackState = {
  state: avSession.PlaybackState.PLAYBACK_STATE_STOP,
  speed: 1.0,
  position:{elapsedTime: 0, updateTime: (new Date()).getTime()},
  bufferedTime: 1000,
  loopMode: avSession.LoopMode.LOOP_MODE_SEQUENCE,
  isFavorite: false,
};
currentSession.setAVPlaybackState(PlaybackState).then(() => {
  console.info('setAVPlaybackState successfully');
}).catch((err) => {
  console.info(`setAVPlaybackState : ERROR : ${err.message}`);
});

// 获取当前session会话对象自身的控制器
currentSession.getController().then((selfController) => {
   console.info('getController successfully');
}).catch((err) => {
   console.info(`getController : ERROR : ${err.message}`);
});

// 获取音频输出设备信息
currentSession.getOutputDevice().then((outputInfo) => {
   console.info(`getOutputDevice successfully, deviceName : ${outputInfo.deviceName}`);
}).catch((err) => {
   console.info(`getOutputDevice : ERROR : ${err.message}`);
});

4.注册控制命令监听

// 注册播放命令监听
currentSession.on('play', () => {
   console.log("调用AudioPlayer.play方法");
   // 设置播放状态
   currentSession.setAVPlaybackState({state: avSession.PlaybackState.PLAYBACK_STATE_PLAY}).then(() => {
       console.info('setAVPlaybackState successfully');
   }).catch((err) => {
       console.info(`setAVPlaybackState : ERROR : ${err.message}`);
   });
});

// 注册暂停命令监听
currentSession.on('pause', () => {
   console.log("调用AudioPlayer.pause方法");
   // 设置播放状态
   currentSession.setAVPlaybackState({state: avSession.PlaybackState.PLAYBACK_STATE_PAUSE}).then(() => {
       console.info('setAVPlaybackState successfully');
   }).catch((err) => {
       console.info(`setAVPlaybackState : ERROR : ${err.message}`);
   });
});

// 注册停止命令监听
currentSession.on('stop', () => {
   console.log("调用AudioPlayer.stop方法");
   // 设置播放状态
   currentSession.setAVPlaybackState({state: avSession.PlaybackState.PLAYBACK_STATE_STOP}).then(() => {
       console.info('setAVPlaybackState successfully');
   }).catch((err) => {
       console.info(`setAVPlaybackState : ERROR : ${err.message}`);
   });
});

// 注册下一首命令监听
currentSession.on('playNext', () => {
   // 如果媒体文件未准备好,则下载并缓存媒体文件,设置准备状态
   currentSession.setAVPlaybackState({state: avSession.PlaybackState.PLAYBACK_STATE_PREPARE}).then(() => {
       console.info('setAVPlaybackState successfully');
   }).catch((err) => {
       console.info(`setAVPlaybackState : ERROR : ${err.message}`);
   });
   // 成功获取媒体文件
   currentSession.setAVMetadata({assetId: '58970105', title: '不如我们明天见'}).then(() => {
       console.info('setAVMetadata successfully');
   }).catch((err) => {
       console.info(`setAVMetadata : ERROR : ${err.message}`);
   });
   console.log("调用AudioPlayer.play方法");
   // 设置播放状态
   let time = (new Date()).getTime();
   currentSession.setAVPlaybackState({state: avSession.PlaybackState.PLAYBACK_STATE_PLAY, position: {elapsedTime: 0, updateTime: time}, bufferedTime:2000}).then(() => {
       console.info('setAVPlaybackState successfully');
   }).catch((err) => {
       console.info(`setAVPlaybackState : ERROR : ${err.message}`);
   });
});

// 注册播放快进命令监听
currentSession.on('fastForward', () => {
   console.log("调用AudioPlayer的倍速播放");
   // 设置播放状态
   currentSession.setAVPlaybackState({speed: 2.0}).then(() => {
       console.info('setAVPlaybackState successfully');
   }).catch((err) => {
       console.info(`setAVPlaybackState : ERROR : ${err.message}`);
   });
});

// 注册跳播命令监听
currentSession.on('seek', (time) => {
   console.log("调用AudioPlayer的seek方法");
   // 设置播放状态
   currentSession.setAVPlaybackState({position: {elapsedTime: time, updateTime: (new Data()).getTime()}}).then(() => {
       console.info('setAVPlaybackState successfully');
   }).catch((err) => {
       console.info(`setAVPlaybackState : ERROR : ${err.message}`);
   });
});

// 注册设置播放速度命令监听
currentSession.on('setSpeed', (speed) => {
   console.log(`调用AudioPlayer的倍速播放 ${speed}`);
   // 设置播放状态
   currentSession.setAVPlaybackState({speed: speed}).then(() => {
       console.info('setAVPlaybackState successfully');
   }).catch((err) => {
       console.info(`setAVPlaybackState : ERROR : ${err.message}`);
   });
});

// 注册设置播放循环模式命令监听
currentSession.on('setLoopMode', (mode) => {
   console.log(`应用自身切换循环模式 ${mode}`);
   // 设置播放状态
   currentSession.setAVPlaybackState({loopMode: mode}).then(() => {
       console.info('setAVPlaybackState successfully');
   }).catch((err) => {
       console.info(`setAVPlaybackState : ERROR : ${err.message}`);
   });
});

// 注册设置歌曲收藏命令监听
currentSession.on('toggleFavorite', (assetId) => {
   console.log(`应用保存当前assetId为喜爱 ${assetId}`);
   // 根据上一次的状态进行切换
   let favorite = mediaFavorite == false ? true : false;
   currentSession.setAVPlaybackState({isFavorite: favorite}).then(() => {
       console.info('setAVPlaybackState successfully');
   }).catch((err) => {
       console.info(`setAVPlaybackState : ERROR : ${err.message}`);
   });
   mediaFavorite = favorite;
});

// 注册媒体按键命令监听
currentSession.on('handleKeyEvent', (event) => {
   console.log(`用户按键 ${event.keyCode}`);
});

// 注册播放设备变化命令监听
currentSession.on('outputDeviceChange', (device) => {
   console.log(`输出设备变更,更新显示 ${device.deviceName}`);
});

5.释放资源

// 取消注册回调
currentSession.off('play');
currentSession.off('pause');
currentSession.off('stop');
currentSession.off('playNext');
currentSession.off('playPrevious');
currentSession.off('fastForward');
currentSession.off('rewind');
currentSession.off('seek');
currentSession.off('setSpeed');
currentSession.off('setLoopMode');
currentSession.off('toggleFavorite');
currentSession.off('handleKeyEvent');
currentSession.off('outputDeviceChange');

// 去激活session并销毁对象
currentSession.deactivate().then(() => {
   currentSession.destroy();
});

调测验证

在媒体应用上点击播放、暂停、下一首等按键,媒体播放状态出现相应变化。

常见问题

1.会话服务端异常 - 现象描述:

会话服务端异常,应用端无法获取服务端的消息响应。如会话服务未运行或者会话服务通信失败。返回错误信息: Session service exception。

  • 可能原因:

会话重启过程中服务被杀。

  • 解决办法

(1)定时重试,超过3s仍失败时,停止对该会话或者控制器进行操作。

(2)销毁当前会话或者会话控制器,并重新创建,如果重新创建失败,则停止会话相关操作。

2.会话不存在 - 现象描述:

会话对象不存在时,向该会话设置参数或者发送命令。返回错误信息: The session does not exist。

  • 可能原因:

会话已被销毁,服务端无会话记录。

  • 解决办法

(1)如果在会话被控端产生该错误,请重新创建会话;如果是会话控制端,请停止向该会话发送查询或者控制命令。

(2)如果在会话管理端产生该错误,请重新查询系统当前会话记录,在创建控制器时传入正确的会话ID。

3.会话未激活 - 现象描述:

会话没有激活时,向会话发送控制命令或者事件。。返回错误信息: The session not active。

  • 可能原因:

会话处于未激活状态。

  • 解决办法

停止发送该命令或事件,监听会话的激活状态,会话激活后恢复发送该命令或事件。

相关实例

提供音乐Demo的代码实例

会话控制端开发指导(播控中心)

基本概念

  • 远端投播:将本地媒体投播到远端设备,通过本地控制器发送命令,可控制远端播放行为。
  • 发送按键命令:控制器通过发送按键事件的方式控制媒体。
  • 发送控制命令:控制器通过发送控制命令的方式控制媒体。
  • 发送系统按键命令:应用拥有调用该接口的系统权限,通过发送按键事件的方式控制媒体,仅系统应用可用。
  • 发送系统控制命令:应用拥有调用该接口的系统权限,通过发送控制命令的方式控制媒体,仅系统应用可用。

接口说明

会话控制端涉及的常用接口如下表所示。接口返回值有两种返回形式:callback和promise,下表中为callback形式接口,promise和callback只是返回值方式不一样,功能相同。更多API说明请参见API文档。

表2:会话控制端常用接口

接口名描述
getAllSessionDescriptors(callback: AsyncCallback<Array<Readonly>>): void获取所有会话的描述符
createController(sessionId: string, callback: AsyncCallback): void创建控制器
sendAVKeyEvent(event: KeyEvent, callback: AsyncCallback): void发送按键命令
getLaunchAbility(callback: AsyncCallback): void拉起应用
sendControlCommand(command: AVControlCommand, callback: AsyncCallback): void发送控制命令
sendSystemAVKeyEvent(event: KeyEvent, callback: AsyncCallback): void发送系统按键命令
sendSystemControlCommand(command: AVControlCommand, callback: AsyncCallback): void发送系统控制命令
castAudio(session: SessionToken‘all’, audioDevices: Array<audio.AudioDeviceDescriptor>, callback: AsyncCallback): void

开发步骤

1.导入模块接口

import avSession from '@ohos.multimedia.avsession';
import {Action, KeyEvent} from '@ohos.multimodalInput.KeyEvent';
import wantAgent from '@ohos.app.ability.wantAgent';
import audio from '@ohos.multimedia.audio';

2.获取会话描述符,创建控制器

// 全局变量定义
let g_controller = new Array<avSession.AVSessionController>();
let g_centerSupportCmd:Set<avSession.AVControlCommandType> = new Set(['play', 'pause', 'playNext', 'playPrevious', 'fastForward', 'rewind', 'seek','setSpeed', 'setLoopMode', 'toggleFavorite']);
let g_validCmd:Set<avSession.AVControlCommandType>;

// 获取会话描述符,创建控制器
avSession.getAllSessionDescriptors().then((descriptors) => {
   descriptors.forEach((descriptor) => {
       avSession.createController(descriptor.sessionId).then((controller) => {
           g_controller.push(controller);
       }).catch((err) => {
           console.error('createController error');
       });
   });
}).catch((err) => {
   console.error('getAllSessionDescriptors error');
});

// 注册会话创建监听,创建控制器
avSession.on('sessionCreate', (session) => {
  // 新增会话,需要创建控制器
  avSession.createController(session.sessionId).then((controller) => {
    g_controller.push(controller);
  }).catch((err) => {
    console.info(`createController : ERROR : ${err.message}`);
  });
});

3.监听AVSession会话状态以及AVSession服务变化

// 注册会话激活状态变更监听
controller.on('activeStateChange', (isActive) => {
  if (isActive) {
    console.log("控制器卡片按键高亮");
  } else {
    console.log("控制器卡片按键变更为无效");
  }
});

// 注册会话销毁监听
controller.on('sessionDestroy', () => {
   console.info('on sessionDestroy : SUCCESS ');
   controller.destroy().then(() => {
       console.info('destroy : SUCCESS ');
   }).catch((err) => {
       console.info(`destroy : ERROR :${err.message}`);
   });
});

// 注册系统会话销毁监听
avSession.on('sessionDestroy', (session) => {
   let index = g_controller.findIndex((controller) => {
       return controller.sessionId == session.sessionId;
   });
   if (index != 0) {
       g_controller[index].destroy();
       g_controller.splice(index, 1);
   }
});

// 注册系统最高优先级会话变更监听
avSession.on('topSessionChange', (session) => {
   let index = g_controller.findIndex((controller) => {
       return controller.sessionId == session.sessionId;
   });
   // 将该会话显示排到第一个
   if (index != 0) {
       g_controller.sort((a, b) => {
           return a.sessionId == session.sessionId ? -1 : 0;
       });
   }
});

// 注册服务异常监听
avSession.on('sessionServiceDie', () => {
   // 服务端异常,应用清理资源
   console.log("服务端异常");
})

4.监听AVSession会话信息变化

// 注册元数据更新监听
let metaFilter = ['assetId', 'title', 'description'];
controller.on('metadataChange', metaFilter, (metadata) => {
   console.info(`on metadataChange assetId : ${metadata.assetId}`);
});

// 注册播放状态更新监听
let playbackFilter = ['state', 'speed', 'loopMode'];
controller.on('playbackStateChange', playbackFilter, (playbackState) => {
   console.info(`on playbackStateChange state : ${playbackState.state}`);
});

// 注册会话支持的命令变更监听
controller.on('validCommandChange', (cmds) => {
   console.info(`validCommandChange : SUCCESS : size : ${cmds.size}`);
   console.info(`validCommandChange : SUCCESS : cmds : ${cmds.values()}`);
   g_validCmd.clear();
   for (let c of g_centerSupportCmd) {
       if (cmds.has(c)) {
           g_validCmd.add(c);
       }
   }
});

// 注册输出设备变更监听
controller.on('outputDeviceChange', (device) => {
   console.info(`on outputDeviceChange device isRemote : ${device.isRemote}`);
});

5.控制AVSession会话行为

// 用户点击播放按键:发送控制命令--播放
if (g_validCmd.has('play')) {
   controller.sendControlCommand({command:'play'}).then(() => {
       console.info('sendControlCommand successfully');
   }).catch((err) => {
       console.info(`sendControlCommand : ERROR : ${err.message}`);
   });
}

// 用户点击循环模式:发送控制命令--单曲循环
if (g_validCmd.has('setLoopMode')) {
   controller.sendControlCommand({command: 'setLoopMode', parameter: avSession.LoopMode.LOOP_MODE_SINGLE}).then(() => {
       console.info('sendControlCommand successfully');
   }).catch((err) => {
       console.info(`sendControlCommand : ERROR : ${err.message}`);
   });
}

// 发送按键事件
let keyItem = {code: 0x49, pressedTime: 123456789, deviceId: 0};
let event = {action: 2, key: keyItem, keys: [keyItem]};
controller.sendAVKeyEvent(event).then(() => {
   console.info('sendAVKeyEvent Successfully');
}).catch((err) => {
   console.info(`sendAVKeyEvent : ERROR : ${err.message}`);
});

// 用户点击卡片空白位置拉起应用
controller.getLaunchAbility().then((want) => {
   console.log("前台拉起应用");
}).catch((err) => {
   console.info(`getLaunchAbility : ERROR : ${err.message}`);
});

// 发送系统媒体按键事件
let keyItem = {code: 0x49, pressedTime: 123456789, deviceId: 0};
let event = {action: 2, key: keyItem, keys: [keyItem]};
avSession.sendSystemAVKeyEvent(event).then(() => {
   console.info('sendSystemAVKeyEvent Successfully');
}).catch((err) => {
   console.info(`sendSystemAVKeyEvent : ERROR : ${err.message}`);
});

// 发送系统控制命令,系统会把控制命令发送到Top会话中
let avcommand = {command: 'toggleFavorite', parameter: "false"};
avSession.sendSystemControlCommand(avcommand).then(() => {
   console.info('sendSystemControlCommand successfully');
}).catch((err) => {
   console.info(`sendSystemControlCommand : ERROR : ${err.message}`);
});

// 投播到其他设备
let audioManager = audio.getAudioManager();
let audioDevices;
await audioManager.getDevices(audio.DeviceFlag.OUTPUT_DEVICES_FLAG).then((data) => {
   audioDevices = data;
   console.info('Promise returned to indicate that the device list is obtained.');
}).catch((err) => {
   console.info(`getDevices : ERROR : ${err.message}`);
});

avSession.castAudio('all', audioDevices).then(() => {
   console.info('createController : SUCCESS');
}).catch((err) => {
   console.info(`createController : ERROR : ${err.message}`);
});

6.释放资源

// 取消注册回调
 controller.off('metadataChange');
 controller.off('playbackStateChange');
 controller.off('sessionDestroy');
 controller.off('activeStateChange');
 controller.off('validCommandChange');
 controller.off('outputDeviceChange');

 // 销毁controller对象
 controller.destroy().then(() => {
     console.info('destroy : SUCCESS ');
 }).catch((err) => {
     console.info(`destroy : ERROR : ${err.message}`);
 });

调测验证

在播控中心点击播放、暂停、下一首等按键,应用播放状态随即发生相应变化。

常见问题

1.控制器不存在 - 现象描述:

会话控制器不存在时,向该控制器发送控制命令或者事件。返回错误信息: The session controller does not exist。

  • 可能原因:

控制器已被销毁。

  • 解决办法

请重新查询系统当前会话记录,并创建对应的会话控制器。

2.远端会话连接失败 - 现象描述:

本端会话与远端会话通信失败。返回错误信息: The remote session connection failed。

  • 可能原因:

设备间通信断开。

  • 解决办法

停止对该会话发送控制命令,并监听输出设备变化,当输出设备发送变化后恢复发送。

3.无效会话命令 - 现象描述:

会话被控端不支持该被控命令或事件。返回错误信息: Invalid session command。

  • 可能原因:

被控端不支持该命令。

  • 解决办法

停止发送该命令或事件,并查询被控会话支持的命令集,发送被控端支持的命令。

4.消息过载 - 现象描述:

会话客户端在一段时间内向服务端发送了过多的消息或者命令,引起服务端消息过载。返回错误信息: Command or event overload。

  • 可能原因:

服务端消息过载。

  • 解决办法

检查自身命令发送是否过于频繁,控制自身查询和控制命令的发送频度。

为了能让大家更好的学习鸿蒙 (OpenHarmony) 开发技术,这边特意整理了《鸿蒙 (OpenHarmony)开发学习手册》(共计890页),希望对大家有所帮助:https://qr21.cn/FV7h05

《鸿蒙 (OpenHarmony)开发学习手册》

入门必看:https://qr21.cn/FV7h05

  1. 应用开发导读(ArkTS)
  2. ……

HarmonyOS 概念:https://qr21.cn/FV7h05

  1. 系统定义
  2. 技术架构
  3. 技术特性
  4. 系统安全

如何快速入门?:https://qr21.cn/FV7h05

  1. 基本概念
  2. 构建第一个ArkTS应用
  3. 构建第一个JS应用
  4. ……

开发基础知识:https://qr21.cn/FV7h05

  1. 应用基础知识
  2. 配置文件
  3. 应用数据管理
  4. 应用安全管理
  5. 应用隐私保护
  6. 三方应用调用管控机制
  7. 资源分类与访问
  8. 学习ArkTS语言
  9. ……

基于ArkTS 开发:https://qr21.cn/FV7h05

1.Ability开发
2.UI开发
3.公共事件与通知
4.窗口管理
5.媒体
6.安全
7.网络与链接
8.电话服务
9.数据管理
10.后台任务(Background Task)管理
11.设备管理
12.设备使用信息统计
13.DFX
14.国际化开发
15.折叠屏系列
16.……

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1424904.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

链式二叉树(1)

目录 二叉树的概念&结构 二叉树的遍历概念 手写二叉树测试 二叉树遍历实现代码 递归图解 前序遍历递归图解 中序序遍历递归图解 后续遍历递归图解 二叉树的概念&结构 二叉树是&#xff1a; 空树非空&#xff1a;根节点&#xff0c;根节点的左子树、根节点的右子…

基于MongoDB实现聊天记录的存储

一、mongodb简介 1.1 mongodb简介 MongoDB是一个基于分布式文件存储的数据库&#xff0c;使用C语言编写。它旨在为WEB应用提供可扩展的高性能数据存储解决方案。MongoDB介于关系数据库和非关系数据库之间&#xff0c;是非关系数据库当中功能最丰富、最像关系数据库的。 Mong…

【TCP】三次握手(建立连接)

前言 在网络通信的世界里&#xff0c;可靠传输协议&#xff08;TCP&#xff09;扮演着重要的角色&#xff0c;它保证了数据包能够按顺序、完整地从发送端传送到接收端。TCP协议中有一个至关重要的机制——三次握手。这一过程确保了两个TCP设备在开始数据传输之前建立起一个稳定…

计算机毕业设计 | SpringBoot 房屋租赁网 房屋租赁平台(附源码)

1&#xff0c;绪论 1.1 背景调研 在房地产行业持续火热的当今环境下&#xff0c;房地产行业和互联网行业协同发展&#xff0c;互相促进融合已经成为一种趋势和潮流。本项目实现了在线房产平台的功能&#xff0c;多种技术的灵活运用使得项目具备很好的用户体验感。 这个项目的…

【Linux】环境基础开发工具的使用(一)

前言&#xff1a;在此之前我们学习了一些Linux的权限&#xff0c;今天我们进一步学习Linux下开发工具的使用。 &#x1f496; 博主CSDN主页:卫卫卫的个人主页 &#x1f49e; &#x1f449; 专栏分类:Linux的深度刨析 &#x1f448; &#x1f4af;代码仓库:卫卫周大胖的学习日记…

长时间佩戴骨传导耳机会损害听力吗?骨传导耳机有什么优点?

如果是正常的使用&#xff0c;是不会对损伤听力的&#xff0c;如果错误的使用&#xff0c;比如说高音量使用&#xff0c;长时间也会出现一定的危害&#xff0c;而且骨传导耳机相比于传统耳机&#xff0c;其优点也要多一些&#xff0c;下面一起看下骨传导耳机都有哪些优点吧。 佩…

dockerpipwork相关测试过程

pipework可以减轻docker实施过程中的工作量&#xff0c;在网上也找了几篇类似的文章&#xff0c;按照相应配置&#xff0c;结果并不相同 如下测试过程记录下&#xff1a; docker run -it --rm --name c1 busybox docker run -it --rm --name c2 busyboxpipework br1 c1 192…

玛格全屋定制携手君子签,实现业务信息、流程、合同全面数字化

中国定制家居领导品牌——玛格全屋定制携手君子签&#xff0c;部署玛格业务系统&#xff0c;将电子签章系统与供应链上下游业务合同签署场景融合&#xff0c;通过无纸化、电子化的签署环境&#xff0c;打造业务“线上审批、签署、归档”闭环&#xff0c;助推业务减负提效。 电…

Redis 布隆过滤器

布隆过滤器 这一篇文章主要是记录布隆过滤器的使用和认识 主要参考了如下的blog https://blog.csdn.net/weixin_42972832/article/details/131211665 他讲的还不错 简单的来说,布隆过滤器,实际上就像是一个集合,拿redis的key来举例来说,布隆过滤器的设置就是去过滤不属于redi…

5、混合模型(Hybrid Models)

将两个预测模型的优势结合起来。 文章目录 1、简介2、组件和残差3、混合预测与残差3.1设计混合模型4、示例 - 美国零售销售1、简介 线性回归擅长推断趋势,但不能学习交互。XGBoost擅长学习交互,但不能推断趋势。在这个课程中,我们将学习如何创建"混合"预测器,这…

分割头篇 | 原创自研 | YOLOv8 更换 SEResNeXtBottleneck 头 | 附详细结构图

左图:ResNet 的一个模块。右图:复杂度大致相同的 ResNeXt 模块,基数(cardinality)为32。图中的一层表示为(输入通道数,滤波器大小,输出通道数)。 1. 思路 ResNeXt是微软研究院在2017年发表的成果。它的设计灵感来自于经典的ResNet模型,但ResNeXt有个特别之处:它采用…

BeanFactory创建过程(基于Servlet)

BeanFactory创建过程&#xff08;基于Servlet&#xff09; 1. 概述1.2 那么问题就来了1.2.1 谁负责AnnotationConfigServletWebServerApplicationContext实例呢&#xff1f;1.2.2 ApplicationContextFactory初始化过程又是怎么样的&#xff1f; 1.3 总结 2. 最后 1. 概述 Anno…

【C++零散小记录】类中重载返回类型为常量引用和非常量引用的函数

#include <iostream>class hyp { public://这里后面必须要加上const修饰符&#xff0c;否则这两个test函数不能重载int const& test() const{std::cout << "const" << std::endl;return num;}//int &test()//{// std::cout << &qu…

吉大计网笔记

Osi七层模型 物理层&#xff1a;比特流的透明传输 数据链路层&#xff1a;ip数据包装成帧并传输&#xff0c;处理相邻节点的数据传输。 网络层&#xff1a;选择路由和交换节点&#xff0c;处理任意节点的数据传输。 运输层&#xff1a;主机进程的数据传输服务&#xff0c;端到端…

雷达DoA估计的跨行业应用--麦克风阵列声源定位(Matlab仿真)

一、概述 麦克风阵列&#xff1a; 麦克风阵列是由一定数目的声学传感器&#xff08;麦克风&#xff09;按照一定规则排列的多麦克风系统&#xff0c;而基于麦克风阵列的声源定位是指用麦克风拾取声音信号&#xff0c;通过对麦克风阵列的各路输出信号进行分析和处理&#xff0c;…

Kubernetes实战(二十一)-event事件持久化

默认情况下&#xff0c; K8S 会将事件保留在 etcd 中一个小时&#xff0c;超过1小时的事件将无法看到&#xff0c;所以 K8S 默认保留事件的时间不足以来更深入的了解集群&#xff0c;所以将事件导出到集群外存储是有必要的&#xff0c;以实现可观测性和告警。 Event事件持久化…

央视见证|“看见中国汽车”走进首家汽车供应链企业东软睿驰

由工业和信息化部支持指导&#xff0c;中国汽车工业协会和央视网联合出品的2023《看见中国汽车》专题东软睿驰篇正式上线&#xff0c;记录品牌向上专项行动走进首家汽车供应链企业&#xff0c;展示东软睿驰围绕“成为OEM 软件定义汽车时代最可信赖的合作伙伴”核心战略的创新发…

IT行业证书大揭秘:哪些证书含金量最高?

文章目录 &#x1f4d6; 介绍 &#x1f4d6;&#x1f4d2; 证书 &#x1f4d2; &#x1f4d6; 介绍 &#x1f4d6; 在IT行业&#xff0c;有许多证书被认为是含金量高的&#xff0c;可以帮助个人在职业发展中取得重要的竞争优势。以下是一些IT行业中被认为含金量高的证书&#x…

信用飞品牌升级——全方位优化用户体验 更周到更暖心

在当今社会,金融科技的迅速发展让信贷服务变得更加便捷。信贷品牌的崛起和发展,正在改变着人们的金融生活。消费者在选择信贷服务时,不仅仅关注信贷的额度和利率,服务体验也成为了一大关注点。一个优秀的信贷品牌,不仅要能满足用户的基本信贷需求,更要在服务体验上赢得用户的认…

基于 Echarts 的 Python 图表库:Pyecahrts交互式的日历图和3D柱状图

文章目录 概述一、日历图和柱状图介绍1. 日历图基本概述2. 日历图使用场景3. 柱状图基本概述4. 柱状图使用场景 二、代码实例1. Pyecharts绘制日历图2. Pyecharts绘制2D柱状图3. Pyecharts绘制3D柱状图 总结 概述 本文将引领读者深入了解数据可视化领域中的两个强大工具&#…