鸿蒙OS开发实战:【穿戴应用】

背景

写HarmonyOS穿戴应用研发,仅仅是为了一线研发人员提供少许的帮助。

在有些公司,可能因为业务的需要,所以要求研发人员一定要在华为手表穿戴上研发特定的功能,并且理所应当的认为这个开发成本就一个顺手的事情。

开发应用顺手的原因无非就几点

  1. 宣传 - HarmonyOS已经看似非常成熟
  2. 实践UI效果 - 研发人员在手机上也能写出绚丽的页面和功能
  3. 汇报 - 会写H5前端,就能立即开发HarmonyOS应用

穿戴研发核心注意点

  1. developer.harmonyos.com 网站中的文档,只能阅读3.0版本
  2. 智能穿戴 和 轻穿戴 应用均采用JS语言开发
  3. 智能穿戴 对应产品 - HUAWEI WATCH 3
  4. 轻穿戴 对应产品 - HUAWEI WATCH GT 2 Pro,HUAWEI WATCH GT 3
  5. 和你产品功能相关的API,切记真机验证
  6. JS调用Java的文档一定要阅读,因为穿戴设备上的JS API功能相对来说比较少
  7. JS语言开发的应用启动时的第一个页面是由 congfig.json 文件中的 module -> js -> pages 中的第一个位置文件决定的,比如如下截图中的红色框文件

重点-JS调用Java

场景

录音docs.qq.com/doc/DUmN4VVhBd3NxdExK前往。

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

效果图

为了快速演示效果,效果图来自IDE

代码说明

这里暂且认为你已阅读过3.0的开发文档,并且已经知晓所有的目录结构和开发语言

js代码包含三部分:1. hml页面 2. js逻辑处理 3. css页面样式

布局

testrecordaudiopage.js

import router from '@system.router';
import featureAbility from '@ohos.ability.featureAbility';
import serviceBridge from '../../generated/ServiceBridge.js';var vm = nullexport default {data: {title: "",button_record: "录音",show_button_record: true,button_play: "播放",show_button_play: true,record: null},onInit() {this.title = "JS 录音";vm = this},onHide() {if(this.record){this.record.stopPlay()this.record.stopRecord()}},swipeEvent(e) {if (e.direction == "right") {router.back()}},async audioRecorderDemo(type) {this.record = new serviceBridge()if (type === 'recordaudio') {if(this.button_record === '录音'){this.record.startRecord().then(value => {if(value.abilityResult == 3){vm.button_record = '停止录音'vm.show_button_play = false}});} else {this.record.stopRecord().then(value => {if(value.abilityResult == 1){vm.button_record = '录音'vm.show_button_play = true}});}} else if (type === 'playaudio') {if(this.button_play === '播放'){this.record.play().then(value => {if(value.abilityResult == 3){vm.button_play = '停止播放'vm.show_button_record = falsevar playTimeStatus = setInterval(()=>{this.record.isPlaying().then(value => {if(!value.abilityResult){vm.button_play = '播放'vm.show_button_record = trueclearInterval(playTimeStatus)}})}, 1000)}})} else {this.record.stopPlay().then(value => {if(value.abilityResult == 1){vm.button_play = '播放'vm.show_button_record = true}})}}}
}

testrecordaudiopage.hml

<div class="container" onswipe="swipeEvent"><text class="title">{{ title }}</text><div class="audiobutton"><button class="buttons_record" show="{{show_button_record}}" onclick="audioRecorderDemo('recordaudio')">{{button_record}}</button><button class="buttons_play" show="{{show_button_play}}" onclick="audioRecorderDemo('playaudio')">{{button_play}}</button></div></div>

testrecordaudiopage.css

.container {width: 100%;flex-direction: column;background-color: black;
}.title {font-size: 25fp;text-align: center;width: 100%;margin: 20px;
}.audiobutton {width: 100%;display: flex;flex-direction: column;align-items: center;
}.buttons_record {width: 45%;height: 15%;font-size: 20fp;text-color: white;background-color: #1F71FF;
}.buttons_play {width: 45%;height: 15%;font-size: 20fp;margin-top: 10vp;text-color: white;background-color: #1F71FF;
}

Java API实现的功能

js/generated/ServiceBridge.js,注意这个文件是自动生成的.

// This file is automatically generated. Do not modify it!
const ABILITY_TYPE_EXTERNAL = 0;
const ABILITY_TYPE_INTERNAL = 1;
const ACTION_SYNC = 0;
const ACTION_ASYNC = 1;
const BUNDLE_NAME = 'com.harvey.hw.wear';
const ABILITY_NAME = 'com.harvey.hw.wear.ServiceBridgeStub';
......
const OPCODE_startRecord = 11;
const OPCODE_stopRecord = 12;
const OPCODE_stopPlay = 13;
const OPCODE_isPlaying = 14;
const OPCODE_play = 15;
const sendRequest = async (opcode, data) => {var action = {};action.bundleName = BUNDLE_NAME;action.abilityName = ABILITY_NAME;action.messageCode = opcode;action.data = data;action.abilityType = ABILITY_TYPE_INTERNAL;action.syncOption = ACTION_SYNC;return FeatureAbility.callAbility(action);
}
class ServiceBridge {......async startRecord() {if (arguments.length != 0) {throw new Error("Method expected 0 arguments, got " + arguments.length);}let data = {};const result = await sendRequest(OPCODE_startRecord, data);return JSON.parse(result);}async stopRecord() {if (arguments.length != 0) {throw new Error("Method expected 0 arguments, got " + arguments.length);}let data = {};const result = await sendRequest(OPCODE_stopRecord, data);return JSON.parse(result);}async stopPlay() {if (arguments.length != 0) {throw new Error("Method expected 0 arguments, got " + arguments.length);}let data = {};const result = await sendRequest(OPCODE_stopPlay, data);return JSON.parse(result);}async isPlaying() {if (arguments.length != 0) {throw new Error("Method expected 0 arguments, got " + arguments.length);}let data = {};const result = await sendRequest(OPCODE_isPlaying, data);return JSON.parse(result);}async play() {if (arguments.length != 0) {throw new Error("Method expected 0 arguments, got " + arguments.length);}let data = {};const result = await sendRequest(OPCODE_play, data);return JSON.parse(result);}
}
export default ServiceBridge;

既然这个文件是自动生成的,那么继续看工程配置。

首先,在 工程根目录/entry/src/main/java 文件夹下的包名(文章举例使用:com.harvey.hw.wear)中创建一个名为ServiceBridge.java的文件

其次,配置初始化和声明ServiceBridge.js文件的注解。为什么注册路径文件是MainAbility, 因为初始化的代码是在MainAbility.java文件中

package com.harvey.hw.wear;import com.harvey.hw.wear.bluetooth.BLEMain;
import ohos.annotation.f2pautogen.ContextInject;
import ohos.annotation.f2pautogen.InternalAbility;
import ohos.app.AbilityContext;
import ohos.bundle.IBundleManager;
import ohos.dcall.DistributedCallManager;
import ohos.hiviewdfx.HiLog;
import ohos.hiviewdfx.HiLogLabel;
import ohos.media.audio.*;import java.io.*;
import java.util.Arrays;@InternalAbility(registerTo = "com.harvey.hw.wear.MainAbility")
public class ServiceBridge {private static final HiLogLabel LABEL_LOG = new HiLogLabel(3, 0xD001100, "ServiceBridge");@ContextInjectAbilityContext abilityContext;......//样例:录音/*** 录音 - 启动* @return*/public int startRecord() {if(isRecording){return 1;}if(abilityContext.verifySelfPermission("ohos.permission.MICROPHONE") == IBundleManager.PERMISSION_DENIED){requestPermissions();return 2;}HiLog.error(LABEL_LOG, "RecordServiceAbility::onStart");init();runRecord();return 3;}/*** 录音 - 停止* @return*/public int stopRecord() {if (isRecording && audioCapturer.stop()) {audioCapturer.release();}isRecording = false;return 1;}private AudioRenderer renderer;private static boolean isPlaying = false;/*** 播放 - 停止* @return*/public int stopPlay() {if(isPlaying && renderer.stop()){renderer.release();}isPlaying = false;return 1;}/*** 获取音频播放状态* @return*/public boolean isPlaying(){return isPlaying;}/*** 播放 - 启动* @return*/public int play() {if(isPlaying){return 1;}isPlaying = true;String Path = "/data/data/"+abilityContext.getBundleName()+"/files/record.pcm";File pcmFilePath = new File(Path);if(!pcmFilePath.isFile() || !pcmFilePath.exists()){isPlaying = false;return 2;}new Thread(new Runnable() {@Overridepublic void run() {AudioStreamInfo audioStreamInfo = new AudioStreamInfo.Builder().sampleRate(SAMPLE_RATE).encodingFormat(ENCODING_FORMAT).channelMask(CHANNEL_OUT_MASK).streamUsage(AudioStreamInfo.StreamUsage.STREAM_USAGE_MEDIA).build();AudioRendererInfo audioRendererInfo = new AudioRendererInfo.Builder().audioStreamInfo(audioStreamInfo).audioStreamOutputFlag(AudioRendererInfo.AudioStreamOutputFlag.AUDIO_STREAM_OUTPUT_FLAG_DIRECT_PCM).sessionID(AudioRendererInfo.SESSION_ID_UNSPECIFIED).bufferSizeInBytes(BUFFER_SIZE).isOffload(false).build();renderer = new AudioRenderer(audioRendererInfo, AudioRenderer.PlayMode.MODE_STREAM);AudioInterrupt audioInterrupt = new AudioInterrupt();AudioManager audioManager = new AudioManager();audioInterrupt.setStreamInfo(audioStreamInfo);audioInterrupt.setInterruptListener(new AudioInterrupt.InterruptListener() {@Overridepublic void onInterrupt(int type, int hint) {if (type == AudioInterrupt.INTERRUPT_TYPE_BEGIN&& hint == AudioInterrupt.INTERRUPT_HINT_PAUSE) {renderer.pause();} else if (type == AudioInterrupt.INTERRUPT_TYPE_BEGIN&& hint == AudioInterrupt.INTERRUPT_HINT_NONE) {} else if (type == AudioInterrupt.INTERRUPT_TYPE_END && (hint == AudioInterrupt.INTERRUPT_HINT_NONE|| hint == AudioInterrupt.INTERRUPT_HINT_RESUME)) {renderer.start();} else {HiLog.error(LABEL_LOG, "unexpected type or hint");}}});audioManager.activateAudioInterrupt(audioInterrupt);AudioDeviceDescriptor[] devices = AudioManager.getDevices(AudioDeviceDescriptor.DeviceFlag.INPUT_DEVICES_FLAG);for(AudioDeviceDescriptor des:devices){if(des.getType() == AudioDeviceDescriptor.DeviceType.SPEAKER){renderer.setOutputDevice(des);break;}}renderer.setVolume(1.0f);renderer.start();BufferedInputStream bis1 = null;try {bis1 = new BufferedInputStream(new FileInputStream(pcmFilePath));int minBufferSize = renderer.getMinBufferSize(SAMPLE_RATE, ENCODING_FORMAT,CHANNEL_OUT_MASK);byte[] buffers = new byte[minBufferSize];while ((bis1.read(buffers)) != -1) {if(isPlaying){renderer.write(buffers, 0, buffers.length);renderer.flush();}}} catch (Exception e) {e.printStackTrace();} finally {if (bis1 != null) {try {bis1.close();} catch (IOException e) {e.printStackTrace();}}}stopPlay();}}).start();return 3;}private AudioCapturer audioCapturer;private static final AudioStreamInfo.EncodingFormat ENCODING_FORMAT = AudioStreamInfo.EncodingFormat.ENCODING_PCM_16BIT;private static final AudioStreamInfo.ChannelMask CHANNEL_IN_MASK = AudioStreamInfo.ChannelMask.CHANNEL_IN_STEREO;private static final AudioStreamInfo.ChannelMask CHANNEL_OUT_MASK = AudioStreamInfo.ChannelMask.CHANNEL_OUT_STEREO;private static final int SAMPLE_RATE = 16000;private static final int BUFFER_SIZE = 1024;private static boolean isRecording = false;private void init() {AudioDeviceDescriptor[] devices = AudioManager.getDevices(AudioDeviceDescriptor.DeviceFlag.INPUT_DEVICES_FLAG);AudioDeviceDescriptor currentAudioType = null;for(AudioDeviceDescriptor des:devices){if(des.getType() == AudioDeviceDescriptor.DeviceType.MIC){currentAudioType = des;break;}}AudioCapturerInfo.AudioInputSource source = AudioCapturerInfo.AudioInputSource.AUDIO_INPUT_SOURCE_MIC;AudioStreamInfo audioStreamInfo = new AudioStreamInfo.Builder().audioStreamFlag(AudioStreamInfo.AudioStreamFlag.AUDIO_STREAM_FLAG_AUDIBILITY_ENFORCED).encodingFormat(ENCODING_FORMAT).channelMask(CHANNEL_IN_MASK).streamUsage(AudioStreamInfo.StreamUsage.STREAM_USAGE_MEDIA).sampleRate(SAMPLE_RATE).build();AudioCapturerInfo audioCapturerInfo = new AudioCapturerInfo.Builder().audioStreamInfo(audioStreamInfo).audioInputSource(source).build();audioCapturer = new AudioCapturer(audioCapturerInfo, currentAudioType);}private void runRecord() {isRecording = true;new Thread(new Runnable() {@Overridepublic void run() {//启动录音audioCapturer.start();File file = new File("/data/data/"+abilityContext.getBundleName()+"/files/record.pcm");if (file.isFile()) {file.delete();}try (FileOutputStream outputStream = new FileOutputStream(file)) {byte[] bytes = new byte[BUFFER_SIZE];while (audioCapturer.read(bytes, 0, bytes.length) != -1) {outputStream.write(bytes);bytes = new byte[BUFFER_SIZE];outputStream.flush();if(!isRecording){outputStream.close();break;}}} catch (IOException exception) {HiLog.error(LABEL_LOG, "record exception," + exception.getMessage());}}}).start();}private void requestPermissions() {String[] permissions = {"ohos.permission.MICROPHONE"};abilityContext.requestPermissionsFromUser(Arrays.stream(permissions).filter(permission -> abilityContext.verifySelfPermission(permission) != IBundleManager.PERMISSION_GRANTED).toArray(String[]::new), 0);}}

第三,如何初始化ServiceBridge.java呢?创建一个中间文件,命名为ServiceBridgeStub.java。

public class MainAbility extends AceAbility {@Overridepublic void onStart(Intent intent) {ServiceBridgeStub.register(this);......}......
}

 ServiceBridgeStub.java 

package com.harvey.hw.wear;import java.lang.Object;
import java.lang.String;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
import ohos.ace.ability.AceInternalAbility;
import ohos.app.AbilityContext;
import ohos.rpc.IRemoteObject;
import ohos.rpc.MessageOption;
import ohos.rpc.MessageParcel;
import ohos.rpc.RemoteException;
import ohos.utils.zson.ZSONObject;public class ServiceBridgeStub extends AceInternalAbility {public static final String BUNDLE_NAME = "com.harvey.hw.wear";public static final String ABILITY_NAME = "com.harvey.hw.wear.ServiceBridgeStub";public static final int ERROR = -1;public static final int SUCCESS = 0;......public static final int OPCODE_startRecord = 11;public static final int OPCODE_stopRecord = 12;public static final int OPCODE_stopPlay = 13;public static final int OPCODE_isPlaying = 14;public static final int OPCODE_play = 15;private static ServiceBridgeStub instance;private ServiceBridge service;private AbilityContext abilityContext;public ServiceBridgeStub() {super(BUNDLE_NAME, ABILITY_NAME);}public boolean onRemoteRequest(int code, MessageParcel data, MessageParcel reply,MessageOption option) {Map<String, Object> result = new HashMap<String, Object>();switch(code) {......case OPCODE_startRecord: {java.lang.String zsonStr = data.readString();ZSONObject zsonObject = ZSONObject.stringToZSON(zsonStr);result.put("code", SUCCESS);result.put("abilityResult", service.startRecord());break;}case OPCODE_stopRecord: {java.lang.String zsonStr = data.readString();ZSONObject zsonObject = ZSONObject.stringToZSON(zsonStr);result.put("code", SUCCESS);result.put("abilityResult", service.stopRecord());break;}case OPCODE_stopPlay: {java.lang.String zsonStr = data.readString();ZSONObject zsonObject = ZSONObject.stringToZSON(zsonStr);result.put("code", SUCCESS);result.put("abilityResult", service.stopPlay());break;}case OPCODE_isPlaying: {java.lang.String zsonStr = data.readString();ZSONObject zsonObject = ZSONObject.stringToZSON(zsonStr);result.put("code", SUCCESS);result.put("abilityResult", service.isPlaying());break;}case OPCODE_play: {java.lang.String zsonStr = data.readString();ZSONObject zsonObject = ZSONObject.stringToZSON(zsonStr);result.put("code", SUCCESS);result.put("abilityResult", service.play());break;}default: reply.writeString("Opcode is not defined!");return false;}return sendResult(reply, result, option.getFlags() == MessageOption.TF_SYNC);}private boolean sendResult(MessageParcel reply, Map<String, Object> result, boolean isSync) {if (isSync) {reply.writeString(ZSONObject.toZSONString(result));} else {MessageParcel response = MessageParcel.obtain();response.writeString(ZSONObject.toZSONString(result));IRemoteObject remoteReply = reply.readRemoteObject();try {remoteReply.sendRequest(0, response, MessageParcel.obtain(), new MessageOption());response.reclaim();} catch (RemoteException exception) {return false;}}return true;}public static void register(AbilityContext abilityContext) {instance = new ServiceBridgeStub();instance.onRegister(abilityContext);}private void onRegister(AbilityContext abilityContext) {this.abilityContext = abilityContext;this.service = new ServiceBridge();this.setInternalAbilityHandler(this::onRemoteRequest);try {Field field = ServiceBridge.class.getDeclaredField("abilityContext");field.setAccessible(true);field.set(this.service, abilityContext);field.setAccessible(false);} catch (NoSuchFieldException | IllegalAccessException e) {ohos.hiviewdfx.HiLog.error(new ohos.hiviewdfx.HiLogLabel(0, 0, null), "context injection fail.");}}public static void deregister() {instance.onDeregister();}private void onDeregister() {abilityContext = null;this.setInternalAbilityHandler(null);}
}

最后,对自动生成js代码的功能,做编译配置

entry 主模块的 build.gradle 文件中添加如下代码

apply plugin: 'com.huawei.ohos.hap'
apply plugin: 'com.huawei.ohos.decctest'ohos {compileSdkVersion 6defaultConfig {compatibleSdkVersion 6// 在文件头部定义JS模板代码生成路径def jsOutputDir = project.file("src/main/js/default/generated").toString()// 在ohos -> defaultConfig中设置JS模板代码生成路径javaCompileOptions {annotationProcessorOptions {arguments = ["jsOutputDir": jsOutputDir] // JS模板代码生成赋值}}}......compileOptions {f2pautogenEnabled true // 此处为启用js2java-codegen工具的开关}}......

至此,关于穿戴应用研发的重点介绍已完成。

如果你还有兴趣,可以尝试实践一下BLE传输数据

结尾

这是去年研发穿戴应用的一个Demo应用工程结构

备注

看的HarmonyOS文档多了, 对于开发语言和文档中的描述容易产生混淆,这里附上一张简单的HarmonyOS 3.0 到 3.1版本的说明

鸿蒙开发岗位需要掌握那些核心要领?

目前还有很多小伙伴不知道要学习哪些鸿蒙技术?不知道重点掌握哪些?为了避免学习时频繁踩坑,最终浪费大量时间的。

自己学习时必须要有一份实用的鸿蒙(Harmony NEXT)资料非常有必要。 这里我推荐,根据鸿蒙开发官网梳理与华为内部人员的分享总结出的开发文档。内容包含了:【ArkTS、ArkUI、Stage模型、多端部署、分布式应用开发、音频、视频、WebGL、OpenHarmony多媒体技术、Napi组件、OpenHarmony内核、Harmony南向开发、鸿蒙项目实战】等技术知识点。

废话就不多说了,接下来好好看下这份资料。

如果你是一名Android、Java、前端等等开发人员,想要转入鸿蒙方向发展。可以直接领取这份资料辅助你的学习。鸿蒙OpenHarmony知识←前往。下面是鸿蒙开发的学习路线图。

针对鸿蒙成长路线打造的鸿蒙学习文档。鸿蒙(OpenHarmony )学习手册(共计1236页)与鸿蒙(OpenHarmony )开发入门教学视频,帮助大家在技术的道路上更进一步。

其中内容包含:

《鸿蒙开发基础》鸿蒙OpenHarmony知识←前往

  1. ArkTS语言
  2. 安装DevEco Studio
  3. 运用你的第一个ArkTS应用
  4. ArkUI声明式UI开发
  5. .……

《鸿蒙开发进阶》鸿蒙OpenHarmony知识←前往

  1. Stage模型入门
  2. 网络管理
  3. 数据管理
  4. 电话服务
  5. 分布式应用开发
  6. 通知与窗口管理
  7. 多媒体技术
  8. 安全技能
  9. 任务管理
  10. WebGL
  11. 国际化开发
  12. 应用测试
  13. DFX面向未来设计
  14. 鸿蒙系统移植和裁剪定制
  15. ……

《鸿蒙开发实战》鸿蒙OpenHarmony知识←前往

  1. ArkTS实践
  2. UIAbility应用
  3. 网络案例
  4. ……

最后

鸿蒙是完全具备无与伦比的机遇和潜力的;预计到年底将有 5,000 款的应用完成原生鸿蒙开发,这么多的应用需要开发,也就意味着需要有更多的鸿蒙人才。鸿蒙开发工程师也将会迎来爆发式的增长,学习鸿蒙势在必行!

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

superset config.py路徑

superset config.py路徑 1.路徑 cd /opt/module/miniconda3/envs/superset/lib/python3.9/site-packages/superset2.找到config.py路徑

【御控物联】JavaScript JSON结构转换(12):对象To数组——键值互换

文章目录 一、JSON结构转换是什么&#xff1f;二、核心构件之转换映射三、案例之《JSON对象 To JSON数组》四、代码实现五、在线转换工具六、技术资料 一、JSON结构转换是什么&#xff1f; JSON结构转换指的是将一个JSON对象或JSON数组按照一定规则进行重组、筛选、映射或转换…

Linux---命令行参数

一、命令行参数 在介绍命令行参数前&#xff0c;我想问大家一个问题&#xff0c;在以前写C/C时&#xff0c;main 函数可不可以带参数&#xff1f; 答案是可以带的&#xff0c;int main(int argc, char* argv[]){}&#xff0c;但平时写代码时也证明了&#xff0c;main 函数的参…

C++多线程:线程的创建、join、detach、joinable方法(二)

1、线程的开始与结束 程序运行起来&#xff0c;生成一个进程&#xff0c;该进程所持有的主线程开始自动运行&#xff0c;main主线程运行完所有的代码从main函数中返回表示整个进程运行完毕&#xff0c;标志着主线程和进程的死亡&#xff0c;等待操作系统回收资源&#xff0c;因…

(七)Feign远程调用

先来看我们以前利用RestTemplate发起远程调用的代码&#xff1a; 存在下面的问题&#xff1a; •代码可读性差&#xff0c;编程体验不统一 •参数复杂URL难以维护 Feign是一个声明式的http客户端&#xff0c;官方地址&#xff1a;https://github.com/OpenFeign/feign 其作用…

【JavaScript 漫游】【048】ES6 规范对数组的扩展记录

文章简介 本篇文章为【JavaScript 漫游】专栏的第 048 篇文章&#xff0c;介绍 ES6 规范对数组的扩展知识点。具体包括&#xff1a; 扩展运算符 ...数组的空位Array.prototype.sort() 的排序稳定性新增的静态方法和实例方法 扩展运算符 含义 扩展运算符&#xff08;spread…

ZYNQ学习之PetaLinux与Vitis的安装

基本都是摘抄正点原子的文章&#xff1a;<领航者 ZYNQ 之嵌入式Linux 开发指南 V3.2.pdf&#xff0c;因初次学习&#xff0c;仅作学习摘录之用&#xff0c;有不懂之处后续会继续更新~ 一、Petalinux安装 1.1、Petalinux资源下载 百度云安装包&#xff1a; Petalinux 安装…

mysql 设置初始密码

link 1.首先输入以下指令&#xff1a; sudo cat /etc/mysql/debian.cnf运行截图如下&#xff1a; 2. 再输入以下指令&#xff1a; mysql -u debian-sys-maint -p//注意! //这条指令的密码输入是输入第一条指令获得的信息中的 password ZCt7QB7d8O3rFKQZ 得来。//请根据自己的实…

java复原IP 地址(力扣Leetcode93)

复原IP 地址 力扣原题链接 问题描述 有效 IP 地址正好由四个整数&#xff08;每个整数位于 0 到 255 之间组成&#xff0c;且不能含有前导 0&#xff09;&#xff0c;整数之间用 ‘.’ 分隔。 例如&#xff1a;“0.1.2.201” 和 “192.168.1.1” 是有效 IP 地址&#xff0c…

【如何解决一些常见的 Composer 错误的保姆级讲解】

&#x1f308;个人主页:程序员不想敲代码啊&#x1f308; &#x1f3c6;CSDN优质创作者&#xff0c;CSDN实力新星&#xff0c;CSDN博客专家&#x1f3c6; &#x1f44d;点赞⭐评论⭐收藏 &#x1f91d;希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提…

游戏领域AI智能视频剪辑解决方案

游戏行业作为文化创意产业的重要组成部分&#xff0c;其发展和创新速度令人瞩目。然而&#xff0c;随着游戏内容的日益丰富和直播文化的兴起&#xff0c;传统的视频剪辑方式已难以满足玩家和观众日益增长的需求。美摄科技&#xff0c;凭借其在AI智能视频剪辑领域的深厚积累和创…

大规模云存储展望|2024逐步复苏,2025全面恢复

SSD以其高速度和低延迟等优点&#xff0c;尤其在容量增长和每GB成本降低方面&#xff0c;SSD的增长速度预计将超过近线硬盘&#xff08;Nearline HDD&#xff09;。尽管HDD在大容量存储方面仍有一定优势&#xff0c;但由于SSD在访问速度、能耗及体积等方面的突出表现&#xff0…