鸿蒙笔记2:将定制文件夹打包到hap并查看安装后的相关信息

1、需求简介

有这样一个需求:lazarus应用程序需要对 data 和 sys 文件夹中的子文件夹及文件进行读写、创建。这在windows平台和linux平台都很容易实现。现在需要在鸿蒙平台实现这些功能。

把2个文件夹放在鸿蒙项目文件夹:

entry\src\main\resources\rawfile

由于lazarus应用对rawfile文件夹没有读写权限,改为将2个文件夹放在

entry\src\main\resources\resfile

hap安装后,resfile 资源会被解压到应用沙箱路径中。

现在需要验证 resfile 下的 data 文件夹是否已正确打包并部署到模拟器,可以通过 hdc 命令在 DevEco Studio 终端中查看

2、 命令行方式查看应用沙箱下 el2/base 目录的文件列表

(包名: com.example.hello20260714b)

perl 复制代码
hdc shell -b com.example.hello20260714b ls -A "./data/storage/el2/base/"

-b {bundleName} 参数表示以指定应用的身份执行命令,这样可以正确访问应用沙箱目录。

运行结果:

.backup

cache

files

haps

preferences

3、查看 haps 目录

perl 复制代码
 hdc shell -b com.example.hello20260714b ls -A "./data/storage/el2/base/haps/"

运行结果:

entry

4、在 click 事件中获取并显示resfile对应的路径代码

修改 index.ets 代码,在日志信息中查看resfile对应的资源路径(resourceDir)

修改 Index.ets,在 click 事件中添加获取并显示路径代码。

TypeScript 复制代码
import { common } from '@kit.AbilityKit';

@Entry
@Component
struct Index {
  @State message: string = 'Hello World';

  build() {
    RelativeContainer() {
      Text(this.message)
        .id('HelloWorld')
        .fontSize($r('app.float.page_text_font_size'))
        .fontWeight(FontWeight.Bold)
        .alignRules({
          center: { anchor: '__container__', align: VerticalAlign.Center },
          middle: { anchor: '__container__', align: HorizontalAlign.Center }
        })
        .onClick(() => {
          this.message = 'Welcome';

          // 获取 resourceDir 路径并打印
          let context = getContext(this) as common.UIAbilityContext;
          console.info(`resourceDir 路径: ${context.resourceDir}`);
        })
    }
    .height('100%')
    .width('100%')
  }
}

点击 hello world,hilog中显示:

07-15 14:09:32.299 3855-3855 A03d00/JSAPP com.examp...0260714b I resourceDir 路径: /data/storage/el1/bundle/entry/resources/resfile

此时仍然不能确认 data 、sys 文件夹是否被正确放在沙箱的 resfile 文件夹中。

5、查看虚拟机中资源路径( resourceDir)包含的内容

修改 index.ets 代码

TypeScript 复制代码
import { common } from '@kit.AbilityKit';
import { fileIo } from '@kit.CoreFileKit';
import { hilog } from '@kit.PerformanceAnalysisKit';
import { fileIo as fs } from '@kit.CoreFileKit';
import { BusinessError } from '@kit.BasicServicesKit';

const DOMAIN: number = 0x0010;
// tag: 日志标签,用于标识日志的来源,便于在日志窗口中筛选
const TAG: string = 'search_dir';

@Entry
@Component
struct Index {
  @State message: string = 'Hello World';
  @State fileList: string[] = [];

  aboutToAppear(): void {
    // 获取context(假设在AbilityStage或UIAbility中)
    let context = getContext(this) as common.UIAbilityContext;

    // resfile资源目录(只读,应用安装后自动解压到此)
    const resDir = context.resourceDir;

    // resourceDir 只读路径 -----------------------------------------------
    hilog.info(DOMAIN, TAG, `只读的 resourceDir 路径: ${resDir}`);

    try {
      // 列出 resourceDir 目录下的所有文件和文件夹
      let list = fileIo.listFileSync(context.resourceDir);
      hilog.info(DOMAIN, TAG, `只读的 resourceDir 根目录内容: ${JSON.stringify(list)}`);

      // 尝试列出 data 子目录
      let dataPath = `${resDir}/data`;
      let dataList = fileIo.listFileSync(dataPath);
      hilog.info(DOMAIN, TAG, `只读的 resourceDir/data 目录内容: ${JSON.stringify(dataList)}`);

      // 尝试列出 sys 子目录
      let sysPath = `${resDir}/sys`;
      let sysList = fileIo.listFileSync(sysPath);
      hilog.info(DOMAIN, TAG, `只读的 resourceDir/sys 目录内容: ${JSON.stringify(sysList)}`);

    } catch (e) {
      hilog.info(DOMAIN, TAG, `列出目录失败: ${(e as Error).message}`);

    }
    // resourceDir 只读路径 ===============================================

    // 沙箱可读写目录 ----------------------------------
    const sandboxDir = context.filesDir;
    const srcPath = `${resDir}/data`;
    const destPath = `${sandboxDir}/data`;

    try {
      hilog.info(DOMAIN, TAG, `可读写的沙箱路径 sandboxDir: ${sandboxDir}`);

      // 先检查目标目录是否存在,不存在则创建
      if (!fs.accessSync(destPath)) {
        fs.mkdirSync(destPath);
      }

      // 将 resfile 中的 data 目录复制到沙箱可读写目录
      fs.copyDirSync(srcPath, destPath);
      hilog.info(DOMAIN, TAG, `复制成功,可在沙箱目录中读写data文件夹: ${destPath}`);

    } catch (error) {
      let err2 = error as BusinessError;
      hilog.info(DOMAIN, TAG, `复制失败: Code: ${err2.code}, message: ${err2.message}`);
    }
    // 沙箱可读写目录 ================================================
  }

  build() {
    RelativeContainer() {
      Text(this.message)
        .id('HelloWorld')
        .fontSize($r('app.float.page_text_font_size'))
        .fontWeight(FontWeight.Bold)
        .alignRules({
          center: { anchor: '__container__', align: VerticalAlign.Center },
          middle: { anchor: '__container__', align: HorizontalAlign.Center }
        })
        .onClick(() => {
          this.message = 'Welcome';

          // 获取 resourceDir 路径并打印
          let context = getContext(this) as common.UIAbilityContext;
          console.info(`resourceDir 路径: ${context.resourceDir}`);
        })
    }
    .height('100%')
    .width('100%')
  }
}

运行后,HiLog 过滤 resourceDir 关键词显示内容:

只读的 resourceDir 路径: /data/storage/el1/bundle/entry/resources/resfile

只读的 resourceDir 根目录内容: "sys","data"

只读的 resourceDir/data 目录内容: "370000000000000000","370000000000000002"

只读的 resourceDir/sys 目录内容: "tpl","reg_help.mht","setup.ini",

可读写的沙箱路径 sandboxDir: /data/storage/el2/base/haps/entry/files

复制失败: Code: 13900015, message: File exists

说明2个定制文件夹打包并安装成功了。

备注:resfile 目录中的资源只能以只读方式访问1,如果需要读写操作,需要先将文件复制到应用的 filesDir 沙箱目录中