【ArkUI进阶练中学】第11课:安全与合规进阶

本节目标

  • 掌握Universal Keystore Kit(HUKS)的密钥全生命周期管理能力,能够使用密钥生成、加密解密、签名验签等核心接口
  • 掌握网络安全传输的核心机制,理解HTTPS证书链校验与双向认证的实现方式,能够正确配置Web组件网络通信安全
  • 掌握权限最小化原则的落地方法,能够按照"声明→检查→申请→使用"的标准流程实现动态权限申请
  • 掌握隐私合规的核心要求,能够正确配置隐私标签、隐私政策和权限使用理由,避免上架审核高频驳回问题
  • 掌握ArkGuard字节码混淆的配置与使用,理解混淆选项的作用范围与局限性,能够正确配置白名单保留规则
  • 能够为应用建立从数据加密、安全传输、权限管控到代码保护的完整安全防护体系

一、密钥管理与数据加密

1.1 Universal Keystore Kit概述

Universal Keystore Kit(密钥管理服务,简称HUKS)向业务/应用提供各类密钥的统一安全操作能力,包括密钥管理(密钥生成/销毁、密钥导入、密钥证明、密钥协商、密钥派生)及密钥使用(加密/解密、签名/验签、访问控制)等功能。

HUKS采用三层架构设计:SDK层 提供密钥管理接口供开发者调用,开发者可根据实际业务选择ArkTS或C API;HUKS服务层 实现密钥会话管理及存储管理;HUKS核心层承载核心功能,包括密钥的密码学运算、明文密钥的加解密、密钥访问控制等。对于具备安全环境(如TEE)的系统、设备,HUKS核心层必须运行在安全环境内。

核心原则:HUKS管理的密钥可以由业务/应用导入或调用HUKS的接口生成。密钥在全生命周期内,其明文仅在安全环境中进行访问操作,不会将明文传递出安全环境。

1.2 密钥生成与使用

以下示例展示使用HUKS生成AES密钥并进行加密解密的完整流程:

typescript 复制代码
import { huks } from '@kit.UniversalKeystoreKit';

// 1. 配置密钥属性
let keyAlias = 'my_aes_key';
let properties: Array<huks.HuksParam> = [
  {
    tag: huks.HuksTag.HUKS_TAG_ALGORITHM,
    value: huks.HuksKeyAlg.HUKS_ALG_AES
  },
  {
    tag: huks.HuksTag.HUKS_TAG_KEY_SIZE,
    value: huks.HuksKeySize.HUKS_AES_KEY_SIZE_256
  },
  {
    tag: huks.HuksTag.HUKS_TAG_PURPOSE,
    value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_ENCRYPT |
           huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_DECRYPT
  },
  {
    tag: huks.HuksTag.HUKS_TAG_PADDING,
    value: huks.HuksKeyPadding.HUKS_PADDING_NONE
  },
  {
    tag: huks.HuksTag.HUKS_TAG_BLOCK_MODE,
    value: huks.HuksCipherMode.HUKS_MODE_GCM
  },
  {
    // 指定密钥存储的安全等级:首次解锁后可访问
    tag: huks.HuksTag.HUKS_TAG_AUTH_STORAGE_LEVEL,
    value: huks.HuksAuthStorageLevel.HUKS_AUTH_STORAGE_LEVEL_CE
  }
];

let options: huks.HuksOptions = { properties: properties };

// 2. 生成密钥
async function generateKey(): Promise<void> {
  await huks.generateKeyItem(keyAlias, options)
    .then(() => {
      console.info('密钥生成成功');
    })
    .catch((err: Error) => {
      console.error('密钥生成失败: ' + JSON.stringify(err));
    });
}

// 3. 使用密钥加密数据
async function encryptData(plainText: Uint8Array): Promise<Uint8Array> {
  const encryptOptions: huks.HuksOptions = {
    properties: properties,
    inData: plainText
  };
  const result = await huks.initSession(keyAlias, encryptOptions);
  const handle = result.handle;
  const sessionResult = await huks.updateSession(handle, encryptOptions);
  const finishResult = await huks.finishSession(handle, encryptOptions);
  return finishResult.outData as Uint8Array;
}

关键要点 :HUKS_TAG_AUTH_STORAGE_LEVEL用于设置密钥的安全等级。HUKS_AUTH_STORAGE_LEVEL_DE表示开机后可访问,HUKS_AUTH_STORAGE_LEVEL_CE表示首次解锁后可访问,HUKS_AUTH_STORAGE_LEVEL_ECE表示解锁状态时可访问。对于登录密码等高敏感数据,应使用CE或ECE级别,确保设备锁屏时密钥不可访问。

1.3 密钥的密文导出与导入

从API version 20开始,HUKS支持以密文形式导出和导入密钥。设置HUKS_TAG_IS_ALLOWED_WRAP为true允许密钥导出,然后调用wrapKeyItem以密文形式导出密钥,调用unwrapKeyItem以密文形式导入密钥。此功能适用于跨设备迁移密钥或备份密钥的场景。

二、网络安全传输

2.1 HTTPS证书链校验机制

当应用通过ArkWeb组件或Network Kit加载HTTPS协议URL时,在TLS握手校验阶段,ArkWeb会调用系统预置的CA根证书,对服务端返回的证书链进行完整性、合法性校验。系统CA证书包含了业界常用的商业CA证书,可以覆盖绝大部分互联网应用和网站的证书链校验需求。

如果校验失败(常见于服务器部署自签名证书的场景),ArkWeb会通过onSslErrorEventReceive和onSslErrorEvent两个回调接口通知应用。

2.2 SSL错误回调的合规处理

正确做法 :在SSL错误回调中,推荐使用系统默认配置(不实现回调),或主动调用handleCancel()取消加载。禁止在回调中调用event.handler.handleConfirm() ,否则会绕过证书校验,导致中间人攻击风险。

typescript 复制代码
Web({ src: 'https://example.com', controller: this.controller })
  .onSslErrorEventReceive((event) => {
    // 合规处理:取消加载,而非确认继续
    event.handler.handleCancel();
    // 可以在此显示自定义错误页面或记录日志
    console.error('SSL证书校验失败,已取消加载');
  })

2.3 双向认证

对于安全要求更高的场景(如金融、企业应用),建议启用双向认证(Mutual TLS)。客户端不仅验证服务端证书,也提供自身证书进行TLS握手,防止伪冒客户端接入。使用Device Certificate Kit可以进行证书链的合法性校验,其证书管理服务在对数字证书凭据的安装和使用时,依赖Universal Keystore Kit的密钥存储和管理能力。

2.4 Web组件网络通信安全配置

在Web组件的网络通信中,需要注意以下安全配置:

混合内容处理 :将mixedMode配置为MixedMode.None(严格模式),禁止HTTPS页面加载HTTP资源,规避混合内容安全风险。

CSP内容安全策略:在生产环境启用内容安全策略(CSP),并对WebView开启HTTPS强制与证书校验。

域名白名单:只对受信域名白名单页面注入JS或传递敏感信息,仅限同源HTTPS。

三、权限最小化实践

3.1 权限使用原则

HarmonyOS权限使用需满足以下原则:应用(包括应用引用的三方库)所需权限必须在应用的配置文件中严格按照权限开发指导逐个声明;权限申请满足最小化原则,禁止申请非必要的、已废弃的权限;应用申请敏感权限时,必须填写权限使用理由字段;应用敏感权限须在对应业务功能执行前动态申请,满足隐私最小化要求;用户拒绝授予某个权限后,应用与此权限无关的其他业务功能应允许正常使用。

3.2 权限类型与授权方式

HarmonyOS权限分为三种授权方式:

system_grant(系统授权) :应用被允许访问的数据不会涉及到用户或设备的敏感信息。系统会在用户安装应用时自动授予权限。

user_grant(用户授权) :应用被允许访问的数据涉及到用户或设备的敏感信息。需要在安装包中申请权限,还需要在应用动态运行时通过弹窗请求用户授权。

ACL授权:一种特殊的授权方式,用于满足特定场景下的权限需求。

权限等级分为normal(低风险,安装时自动授予)、system_basic(中等风险,部分需要用户授权)、system_core(高风险,仅授予系统应用)。

3.3 动态权限申请的完整流程

权限申请遵循"检查→申请→使用→降级"的标准流程:

typescript 复制代码
import { abilityAccessCtrl, common, Permissions } from '@kit.AbilityKit';
import { BusinessError } from '@kit.BasicServicesKit';

// 1. 在 module.json5 中声明权限和使用理由
// {
//   "requestPermissions": [{
//     "name": "ohos.permission.CAMERA",
//     "reason": "$string:camera_reason",
//     "usedScene": { "abilities": ["EntryAbility"], "when": "inuse" }
//   }]
// }

const permissions: Array<Permissions> = ['ohos.permission.CAMERA'];

async function requestCameraPermission(
  context: common.UIAbilityContext): Promise<boolean> {
  const atManager = abilityAccessCtrl.createAtManager();

  try {
    // 2. 检查权限状态
    const result = await atManager.requestPermissionsFromUser(
      context, permissions);

    // 3. 根据授权结果决定后续操作
    if (result.authResults[0] === 0) {
      console.info('相机权限已授权');
      return true;
    } else {
      console.warn('相机权限被拒绝');
      // 4. 降级处理:引导用户手动开启或提供替代方案
      return false;
    }
  } catch (err) {
    const e = err as BusinessError;
    console.error(`权限申请失败: ${e.code}, ${e.message}`);
    return false;
  }
}

3.4 权限组机制

为减少权限弹窗数量,系统将逻辑紧密相关的user_grant权限组合在一起形成权限组。当应用请求权限时,同一个权限组的权限会在一个弹窗内一起请求用户授权。例如,位置权限组可能包含前台位置和后台位置两个子权限。开发者在申请时应注意权限组的归属关系,合理设计申请时机。

四、隐私合规

4.1 隐私合规高频驳回问题

根据华为应用市场审核数据,隐私合规相关的驳回问题集中在以下八类高频场景:

TOP1:用户同意隐私政策前获取个人信息。所有个人信息获取行为必须在用户同意隐私政策后触发。技术自检时需检查代码日志与调用栈,确保所有个人信息获取行为均在用户同意后触发。

TOP2:权限申请超出必要范围 。遵循权限最小化原则,仅申请业务功能所必要的权限,并在module.json5的requestPermissions标签中声明权限使用场景。

TOP3:隐私标签缺失。如果应用存在收集个人信息的行为,需要勾选填写隐私标签,同时明确使用场景和目的。填写入口在AppGallery Connect > APP与元服务 > 对应应用名称 > 版本信息 > 隐私标签信息录入。

TOP4:隐私政策未以明示同意方式征得同意。征得用户同意的页面不得"默认同意"或"登录即同意",需要增设勾选框并设为默认未勾选状态,由用户主动操作同意。

TOP5:隐私政策不完整。需要以隐私政策弹窗等形式清晰明示处理个人信息的目的、方式和范围,包括静默状态或后台运行时的收集行为。

TOP6:隐私政策开发者信息不一致。隐私政策内的开发者名称及应用名称均需与在AppGallery Connect上提交的信息一致。

4.2 隐私政策与代码行为一致性

审核员会把隐私政策从头到尾读一遍,然后实际操作应用,看收集的数据和隐私政策里写的是否一致。开发者应将代码里所有用到权限、所有调用SDK、所有收集用户数据的地方列一个清单,然后对照这个清单逐条检查隐私政策有没有覆盖。重点检查项包括:应用声明了哪些权限,隐私政策里有没有说明每个权限的用途;第三方SDK有哪些,每个SDK的名称、提供方、收集的数据类型、用途是否写明;有没有收集用户位置、通讯录、相机、麦克风等敏感信息,隐私政策里有没有说明收集目的和使用方式。

4.3 隐私合规开发实践

首次启动隐私弹窗 :应用首次启动时必须弹出隐私政策弹窗,用户同意之前不能采集任何个人信息。module.json5中需要配置隐私政策相关字段,接入的第三方SDK如果有数据采集行为,也要在隐私标签里声明。

敏感权限申请时机:敏感权限必须在运行时动态申请,且申请时机不能过早。应用一启动就弹出一堆权限请求,是审核中常见的驳回原因。应在对应业务功能执行前才申请权限。

日志脱敏:应用运行日志中不应打印用户敏感信息,如手机号、身份证号、密码等。日志脱敏是上架审核的检查项之一。

五、代码保护与加固

5.1 ArkGuard字节码混淆

ArkGuard是HarmonyOS提供的源码混淆工具,支持ArkTS/TS/JS语言,将代码中的函数名、类名、文件名等标识符修改为无意义的短名称,增加逆向工程难度,同时缩小代码体积。

开启混淆的条件 :工程为Stage模型、在Release编译模式下、在模块的build-profile.json5文件中开启混淆配置。从API version 12版本起,默认启用四项推荐的混淆选项:-enable-property-obfuscation(属性名称混淆)、-enable-toplevel-obfuscation(顶层作用域名称混淆)、-enable-filename-obfuscation(文件名混淆)、-enable-export-obfuscation(导入导出名称混淆)。

5.2 混淆配置

在模块的build-profile.json5中配置混淆:

json5 复制代码
{
  "buildOption": {
    "arkOptions": {
      "obfuscation": {
        "ruleOptions": {
          "enable": true,
          "files": ["./obfuscation-rules.txt"]
        }
      }
    }
  }
}

在obfuscation-rules.txt中配置混淆选项:

text 复制代码
# 开启属性名称混淆
-enable-property-obfuscation
# 开启顶层作用域名称混淆
-enable-toplevel-obfuscation
# 开启文件名混淆
-enable-filename-obfuscation
# 保留需要反射调用的属性名
-keep-property-name
  onPageShow
  onPageHide
  aboutToAppear
# 保留全局名称
-keep-global-name
  MyGlobalFunction

5.3 混淆的局限性

ArkGuard提供的是面向方舟字节码的基础名称混淆,不支持高级混淆能力:控制流混淆(如控制流平坦化、虚假分支插入)、数据混淆(如对常量、字面量或内存数据布局做加密与变换)、指令替换或插入无关指令、虚拟机保护/加壳等。

由于ArkGuard仅支持基础混淆能力,开发者不应只依赖ArkGuard来保证应用的安全性。对于源码安全有高要求的开发者,应考虑使用应用加密、第三方安全加固等安全措施来保护代码。多家安全加固厂商已经启动了HarmonyOS开发适配,但由于HarmonyOS代码签名、应用加密等安全机制的限制,以及应用市场上架审核的纯净安全要求,三方加固厂商提供的安全加固内容必须满足相关要求。

5.4 混淆白名单配置

混淆规则写不好,线上直接崩。需要使用-keep-property-name来保留指定的属性名称,使用-keep-global-name保留指定的导出/导入名称,使用-keep-file-name保留文件路径及名称。DevEco Studio提供了混淆助手工具(ObfuscationHelper),可以根据模块和场景对源码进行扫描,快速识别需要配置的保留选项和白名单字段,一键生成白名单混淆规则文件。

六、安全编码最佳实践

6.1 数据安全

应用程序关键数据应该存放在私有目录下,并设置合理的访问权限。应用程序中的敏感个人信息建议加密存储,用于加密的密钥应妥善保存。敏感个人信息包括聊天记录、搜索记录、登录密码等,登录密码等短敏感数据可以使用Asset Store Kit(关键资产存储开发服务)进行存储。

避免将应用私有数据写入公共数据库、存储区中。应用避免将个人数据写入settings数据库。应用程序中用户名密码应使用标准TextInput控件,指定准确的输入类型type(如用户名指定为InputType.USER_NAME,密码指定为InputType.Password等),以支持系统识别关键数据进行安全保护增强。

6.2 通信安全

对跨信任边界传入的参数须进行合法性判断,防止应用异常崩溃。建议使用HTTPS代替HTTP进行通信,并对HTTPS证书进行严格校验。

所有外部输入的数据必须进行严格的校验和过滤,防止SQL注入、XSS等攻击。

6.3 编码安全

涉及外部开源代码或代码漏洞的情况,须关注代码的安全动态和版本更新情况并及时修复。使用官方推荐版本的API接口,不应使用系统废弃的API。代码须通过官方工具的检测,提升代码的可靠性、安全性和代码质量。

建议开启安全编译选项,缓解漏洞带来的潜在风险。建议应用代码通过官方提供的工具进行混淆,防止攻击者针对性的攻击。

七、多元化习题

习题 1(判断题)

题目:在HUKS中生成的密钥,其明文可以在应用主线程中直接读取和使用。

答案:错误

解读:HUKS管理的密钥在全生命周期内,其明文仅在安全环境中进行访问操作,不会将明文传递出安全环境。开发者通过HUKS接口进行加密解密和签名验签操作,但无法直接获取密钥明文。

习题 2(单选题)

题目:以下哪种HUKS密钥安全等级表示密钥在设备首次解锁后才可访问?

A. HUKS_AUTH_STORAGE_LEVEL_DE

B. HUKS_AUTH_STORAGE_LEVEL_CE

C. HUKS_AUTH_STORAGE_LEVEL_ECE

D. HUKS_AUTH_STORAGE_LEVEL_NE

答案:B

解读 :HUKS_AUTH_STORAGE_LEVEL_DE表示开机后可访问,HUKS_AUTH_STORAGE_LEVEL_CE表示首次解锁后可访问,HUKS_AUTH_STORAGE_LEVEL_ECE表示解锁状态时可访问。对于登录密码等高敏感数据,应使用CE或ECE级别。

习题 3(多选题)

题目:关于ArkGuard混淆的局限性,以下说法正确的有(多选):

A. ArkGuard支持控制流混淆

B. ArkGuard不支持数据混淆

C. ArkGuard不支持虚拟机保护/加壳

D. ArkGuard仅支持基础名称混淆

答案:B、C、D

解读:ArkGuard提供的是面向方舟字节码的基础名称混淆,不支持控制流混淆(如控制流平坦化、虚假分支插入)、数据混淆(如对常量、字面量或内存数据布局做加密与变换)、指令替换或插入无关指令、虚拟机保护/加壳等高级混淆能力。

习题 4(代码填空题)

题目:请补全以下代码,在SSL错误回调中合规处理证书校验失败。

typescript 复制代码
Web({ src: 'https://example.com', controller: this.controller })
  .______________((event) => {
    // 合规处理:取消加载
    event.handler.______________();
  })

答案 :onSslErrorEventReceive、handleCancel

解读 :onSslErrorEventReceive是SSL错误回调接口,当证书校验失败时触发。禁止在回调中调用handleConfirm(),应该调用handleCancel()取消加载,避免绕过证书校验导致中间人攻击风险。

习题 5(代码改错题)

题目:以下权限申请代码存在合规问题,请指出并修正。

typescript 复制代码
@Entry
@Component
struct Index {
  aboutToAppear(): void {
    // 应用启动时立即申请所有权限
    const atManager = abilityAccessCtrl.createAtManager();
    const permissions: Array<Permissions> = [
      'ohos.permission.CAMERA',
      'ohos.permission.MICROPHONE',
      'ohos.permission.LOCATION',
      'ohos.permission.READ_CONTACTS'
    ];
    atManager.requestPermissionsFromUser(this.getUIContext().getHostContext(), permissions);
  }

  build() {
    Column() {
      Text('首页')
    }
  }
}

答案:该代码在应用启动时就申请了所有权限,违反了"应用敏感权限须在对应业务功能执行前动态申请"的原则。敏感权限申请时机不能过早,应用一启动就弹出一堆权限请求是审核中常见的驳回原因。修正方案是将权限申请移到对应业务功能执行前:

typescript 复制代码
@Entry
@Component
struct Index {
  // 不在 aboutToAppear 中申请权限

  build() {
    Column({ space: 16 }) {
      Text('首页')

      // 在需要使用相机时才申请
      Button('拍照')
        .onClick(async () => {
          const context = this.getUIContext().getHostContext();
          const granted = await requestCameraPermission(context);
          if (granted) {
            // 打开相机
          }
        })

      // 在需要使用定位时才申请
      Button('获取位置')
        .onClick(async () => {
          // 申请定位权限
        })
    }
  }
}

解读:敏感权限须在对应业务功能执行前动态申请,满足隐私最小化要求。用户拒绝授予某个权限后,应用与此权限无关的其他业务功能应允许正常使用。

习题 6(简答题)

题目:简述HUKS的核心功能及其三层架构。

答案:HUKS向业务/应用提供各类密钥的统一安全操作能力,核心功能按照密钥生命周期划分包括:密钥生成(随机生成密钥,明文仅在安全环境中访问)、密钥导入(将外部生成的密钥导入HUKS管理)、加密/解密(使用密钥加密或解密数据)、签名/验签(认证消息内容及发送者身份)、密钥协商(两个或多个实体共同建立会话密钥)、密钥封装(通过非对称密钥安全建立共享密钥,支持后量子密码算法)、密钥派生(从一个现有密钥派生新密钥)、访问控制(确保密钥不会被越权访问)、密钥删除(安全删除密钥数据)、密钥证明(为公钥签发证书证明密钥合法性)。三层架构为:SDK层提供密钥管理接口供开发者调用;HUKS服务层实现密钥会话管理及存储管理;HUKS核心层承载密钥的密码学运算、明文密钥的加解密、密钥访问控制等核心功能,必须运行在安全环境内。

解读:HUKS是HarmonyOS安全体系的基石,为应用提供从密钥生成到销毁的全生命周期管理。核心设计理念是密钥明文永不出安全环境,确保即使系统被攻破,密钥也不会泄露。

习题 7(简答题)

题目:简述HarmonyOS应用上架时隐私合规的高频驳回问题及改进建议。

答案:隐私合规高频驳回问题包括八类:用户同意隐私政策前获取个人信息,改进建议是确保所有个人信息获取行为均在用户同意后触发;权限申请超出必要范围,改进建议是遵循权限最小化原则,仅申请业务功能所必要的权限;隐私标签缺失,改进建议是勾选填写隐私标签并明确使用场景和目的;隐私政策未以明示同意方式征得同意,改进建议是增设勾选框并设为默认未勾选状态;隐私政策不完整,改进建议是以隐私政策弹窗等形式清晰明示处理个人信息的目的、方式和范围;隐私政策开发者信息不一致,改进建议是确保隐私政策内的开发者名称及应用名称均与AppGallery Connect上提交的信息一致。

解读:隐私合规是应用上架审核的重灾区。开发者需要将代码里所有用到权限、调用SDK、收集用户数据的地方列一个清单,对照隐私政策逐条检查覆盖情况,确保代码行为与隐私政策描述一致。

八、本节知识点总结

密钥管理与数据加密

Universal Keystore Kit(HUKS)提供密钥全生命周期管理能力,包括密钥生成、导入、加密解密、签名验签、密钥协商、密钥派生等。密钥明文仅在安全环境中访问,不会传递出安全环境。通过HUKS_TAG_AUTH_STORAGE_LEVEL设置密钥安全等级。

网络安全传输

HTTPS证书链校验是保障数据传输安全的核心机制,系统调用预置CA根证书对服务端证书链进行完整性、合法性校验。SSL错误回调中应调用handleCancel()取消加载,禁止调用handleConfirm()。Web组件需配置MixedMode.None严格模式。

权限最小化

权限申请遵循"声明→检查→申请→使用→降级"标准流程。应用敏感权限须在对应业务功能执行前动态申请,用户拒绝后无关功能应正常使用。系统将逻辑紧密相关的权限组合成权限组,减少弹窗数量。

隐私合规

隐私合规高频驳回问题包括用户同意前获取个人信息、权限超出必要范围、隐私标签缺失、隐私政策未明示同意等。隐私政策必须与实际代码行为一致,开发者需将权限、SDK、数据收集行为列清单逐条对照。

代码保护与加固

ArkGuard提供基础名称混淆,支持属性、顶层作用域、文件名、导入导出名称混淆。不支持控制流混淆、数据混淆等高级能力。需通过-keep-property-name等规则配置白名单,避免混淆导致的运行时异常。

安全编码实践

关键数据存放在私有目录并加密存储,敏感个人信息使用Asset Store Kit存储。使用HTTPS代替HTTP并对证书严格校验。对跨信任边界传入的参数进行合法性判断。关注开源代码安全动态并及时修复漏洞。

下节预告

第12课将进入ArkUI的应用架构演进与遗留系统迁移的学习,涵盖从Stage模型到未来架构的演进路径、存量应用迁移策略以及渐进式重构方法论。

相关推荐
熊猫钓鱼>_>2 小时前
Kotlin Multiplatform for OpenHarmony 实战:为 Reaktive 实现响应式原语适配(完整版 · 含摘要目录与技术图表)
华为·kotlin·大模型·ai编程·harmonyos·适配·reaktive
Mr_Macallon3 小时前
C++回顾(基础)(01)
c语言·开发语言·c++·学习
sunoo-2294 小时前
【ARM嵌入式学习笔记第十天】i.MX6ULL eLCDIF控制器驱动RGB LCD全解析(硬件原理+寄存器配置+裸机代码)
arm开发·笔记·学习
kaiyou20264 小时前
用户研究岗秋招,统计分析能力怎么学习和证明?
数据库·python·学习
知识分享小能手4 小时前
C++ 学习教程,从入门到精通,string类和标准模板库 — 完整知识点详解(16)
开发语言·c++·学习
inferno6 小时前
SVN学习笔记(二)
笔记·学习·svn
李游Leo6 小时前
HarmonyOS 7 + Spatial Recon Kit-C++:3DGS 高斯参数的非有限值隔离与可渲染性门禁【鸿蒙心迹】
开发语言·c++·3d·harmonyos
熊猫钓鱼>_>6 小时前
Kotlin Multiplatform for OpenHarmony 实战:为 MVIKotlin 实现单向数据流适配
华为·ai编程·鸿蒙·openharmony·适配·数据流·mvkotlin
传奇开心果编程6 小时前
【ArkUI进阶练中学】第12课:应用架构演进与遗留系统迁移
学习·ui·华为·harmonyos