HarmonyOS鸿蒙Next中arkts与napi能否操作同一个范围的preferences?

HarmonyOS鸿蒙Next中arkts与napi能否操作同一个范围的preferences? 如题,我在arkts中打开了一个preferences,文件名是configXXX,之后对这个preferences做了一些操作:

let p = preferences.getPreferencesSync(context, {
    name: 'configXXX'
})
p.putSync("name", "xyz") // 放进去了一个键值对
p.flush()

注:这个context参数不是ApplicationContext,而是当前Ability的context,所以拿到的preferences系列文件会存放到/data/storage/el2/base/haps/entry/preferencesDir目录中。

我想在napi层拿到这个名为configXXX的preferences,并拿出已经存储的name属性值:

int openResult;
OH_PreferencesOption *options = OH_PreferencesOption_Create();
OH_PreferencesOption_SetFileName(options, "configXXX");
OH_Preferences *pref = OH_Preferences_Open(options, &openResult);
OH_PreferencesOption_Destroy(options);

if (openResult == 0) {
    char *value = nullptr;
    uint32_t valueStrLength = 0;
    int resultCode = OH_Preferences_GetString(pref, "name", &value, &valueStrLength);
    
    if (resultCode == 0 && value != nullptr) {
        Log(value); // 此处我想打印一下value。
    }
    OH_Preferences_FreeString(value);
}

我没有找到在napi层为preferences设置context的方法,因此这里通过OH_Preferences_Open方法打开的preferences是全局的,相关文件会存放到/data/storage/el2/base/preferencesDir目录下。可见这个目录与上边ArkTS打开的preferences是不同的。因此我在napi层没有拿到name属性值。

如果把ArkTS层的preferences改为使用context.getApplicationContext()来打开,那么ArkTS与napi倒是可以访问同一个preferences,但之前旧的preferences中存储的数据就不能用了(因为旧preferences没有被打开)。

有没有什么办法能够在napi层也能访问到AbilityContext范围的preferences呢?


更多关于HarmonyOS鸿蒙Next中arkts与napi能否操作同一个范围的preferences?的实战教程也可以访问 https://www.itying.com/category-93-b0.html

11 回复

开发者您好,目前首选项ndk接口仅支持获取app层级的首选项,暂不支持获取模块级首选项。 针对目前的场景,可以考虑在新版本升级时在ArkTS侧将模块级首选项数据转存到app层级的首选项中,升级后在ArkTS侧和C侧都仅操作app层级的首选项。 若对在C侧获取模块级首选项有强烈诉求,麻烦完善一下以下信息:

请问您是在什么样的业务场景中使用该能力,交互流程是怎样的,在哪一个环节遇到了问题?方便说明能力不满足可能带来的影响:什么时间用到?是否高频?有无三方库可以做到?若提供该能力,是否会造成大工作量返工?请您注意提供的内容不要包含您或第三方的非公开信息,如给您带来不便,敬请谅解。

更多关于HarmonyOS鸿蒙Next中arkts与napi能否操作同一个范围的preferences?的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


兄弟,我发的都是小艺说的不知对不对你查查!

图片

嗯,还不能修改ArkTS层preferences的context范围,为了保证应用升级后,用户之前存的一堆配置项还能用。

关于ArkTS层Preferences的context范围问题,需结合HarmonyOS数据管理机制实现兼容性升级。 以下是关键分析及解决方案:

一、问题核心

1.上下文范围限制 Preferences实例的 context 参数(类型为void*)在注册数据观察器OH_Preferences_RegisterDataObserver应用上下文指针传入(检索信息 1)。该参数范围在现有设计中不可修改,否则会导致升级后无法访问历史存储的配置项。

2.升级兼容性要求 若修改 context范围,可能破坏以下机制: ◇已存储的KV数据路径绑定原始context ◇数据观察者回调OH_PreferencesDataObserver依赖原始上下文指针匹配变更事件

二、兼容性方案

1.保留原始context访问

// 注册观察器时固定使用原始context
OH_Preferences_RegisterDataObserver(
preference,
originalContext, // 使用旧版context指针
(void* ctx, const OH_PreferencesPair* pairs, size_t keyCount) {
// 回调中通过ctx访问旧数据
...
}
);

2.数据迁移机制 若必须修改context范围,需分步操作:

  1. 读取历史数据
OH_Preferences_GetString(oldPreferences, "cor
  1. 写入新context范围
OH_Preferences_SetString(newPreferences, "cc
  1. 双观察器过渡 同时注册新旧context的观察器,确保数据变更同步

3.存储模式校验 使用OH_Preferences_IsStorageTypeSupported

bool isSupported;
OH_Preferences_IsStorageTypeSupported(STOI
// 根据结果选择存储策略

三、设计约束

组件 约束说明
context指针 必须与创建Preferences实例时的上下文一致,否则无法访问持久化数据
数据观察器回调函数OH_PreferencesDataObserver 严格依赖初始context
// NAPI层(C++)
static napi_value ReadPrefs(napi_env env, napi_callback_info info) {
  size_t argc = 1;
  napi_value args;
  napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);

  // 1. 获取ArkTS传入的路径
  char path;
  size_t path_len;
  napi_get_value_string_utf8(env, args, path, sizeof(path), &path_len);

  // 2. 直接操作文件
  FILE* file = fopen(path, "r");
  if (file) {
    char buffer;
    while (fgets(buffer, sizeof(buffer), file)) {
      // 解析文件内容获取"name"值
      if (strstr(buffer, "name")) {
        Log("Value: %s", strchr(buffer, '=') + 1);
      }
    }
    fclose(file);
  }
  return nullptr;
}

不太行,我没法对这些preferences文件手动解密。

解决方案:使用正确的 NAPI 接口访问 Ability Context 下的 Preferences

问题的核心在于,您之前使用的 OH_Preferences_Open 方法默认访问的是全局作用域(ApplicationContext)的 Preferences,而您存放数据的 configXXX 在 Ability Context 的独立目录下。

您需要寻找并使用能够指定上下文(Context)的 NAPI 接口来打开 Preferences。

根据 HarmonyOS 的设计,每个 Ability Context 都有自己独立的存储目录,其下的 Preferences 文件也由该 Context 管理并加密。因此,必须获取到对应 Ability 的 Context 对象,并将其传递给 NAPI 层,才能打开和操作其中的数据。

具体步骤建议如下:

  1. 查找正确的 NAPI API 请仔细查阅 HarmonyOS 的官方 NAPI 开发文档,寻找是否存在类似于 OH_Preferences_OpenWithContext 或类似名称的函数,该函数应接收一个 Context 参数。

  2. 从 ArkTS 层传递 Context 如果找到了上述 API,您需要在 ArkTS 层将当前 Ability 的 Context 对象作为参数传递给 NAPI 模块中的函数。

  3. 在 NAPI 层使用 Context 打开 Preferences 在 NAPI 函数内部,使用接收到的 Context 对象调用新找到的 API,从而打开位于该 Ability Context 下的 configXXX Preferences,并安全地读取其中的键值对。

总结来说,直接操作加密文件不是正确的途径。您必须通过 HarmonyOS 提供的、受信任的 API 来访问这些数据,确保解密过程由系统安全地处理。

// ArkTS层
import { preferences } from '@kit.ArkData';
import fs from '@ohos.file.fs';

let context = ...; // AbilityContext
let p = preferences.getPreferencesSync(context, { name: 'configXXX' });
let path = context.filesDir + "/preferences/" + 'configXXX'; // 真实路径需拼接

// 将path传递给NAPI
nativeModule.readPrefs(path);

在ArkTS层使用AbilityContext的 preferences.getPreferencesSync 创建的Preferences文件与NAPI层使用 OH_Preferences_Open 访问的路径不同,导致无法直接读取。以下是解决方案:

核心问题

  • ArkTS路径: /data/storage/el2/base/haps/entry/preferencesDir (Ability作用域)
  • NAPI路径: /data/storage/el2/base/preferencesDir (全局作用域)
  • 根本原因:NAPI的 OH_Preferences_Open 未提供设置AbilityContext的接口

解决方案 方法1:通过ArkTS传递文件路径(推荐) 在ArkTS层获取Preferences文件路径,通过NAPI接口传递给C++层:

在HarmonyOS Next中,arkTS与NAPI可以操作同一个范围的Preferences。Preferences数据基于应用包名进行存储隔离,arkTS和NAPI属于同一应用,因此它们访问的是同一份Preferences文件。两者通过统一的Preferences实例接口读写数据,数据变更会实时同步。

在HarmonyOS Next中,ArkTS和NAPI确实可以操作同一个范围的Preferences,但需要确保访问的是同一个存储路径。

从你的描述来看,问题在于ArkTS使用的是AbilityContext,而NAPI默认使用的是全局路径。要解决这个问题,你需要在NAPI层指定正确的文件路径。

解决方案:

  1. 在NAPI层指定完整的文件路径:

    OH_PreferencesOption *options = OH_PreferencesOption_Create();
    OH_PreferencesOption_SetFileName(options, "configXXX");
    OH_PreferencesOption_SetPath(options, "/data/storage/el2/base/haps/entry/preferencesDir");
    OH_Preferences *pref = OH_Preferences_Open(options, &openResult);
    
  2. 或者通过ArkTS将路径传递给NAPI:

    // ArkTS层
    let path = context.filesDir + "/preferencesDir";
    nativeModule.openPreferences("configXXX", path);
    
    // NAPI层
    static napi_value OpenPreferences(napi_env env, napi_callback_info info) {
        // 解析ArkTS传递的文件名和路径参数
        // 使用OH_PreferencesOption_SetPath设置路径
    }
    

关键点:

  • AbilityContext的Preferences存储在应用沙箱的特定路径下
  • NAPI的OH_Preferences_Open默认使用全局路径,需要显式设置路径参数
  • 确保ArkTS和NAPI使用相同的文件路径才能访问同一份Preferences数据

这样配置后,ArkTS和NAPI就能操作同一个Preferences文件了。

回到顶部