1 关键字

3.1 Release;preferences.getAll()

2 问题描述

开发板型号:rk3568

OH版本:OpenHarmony 3.1 Release

问题现象:'@ohos.data.preferences'模块下的getAll方法调用失败,报错为不可调用。

3 问题原因

3.1 正常机制

调用'@ohos.data.preferences'模块下的getAll方法,从Preferences实例中获取含有所有键值的Object对象,正常回调并打印出Object对象值。

3.2 异常机制

调用'@ohos.data.preferences'模块下的getAll方法,从Preferences实例中获取含有所有键值的Object对象时,getAll方法调用失败并报错:不可调用。

4 解决方案

修改3.1 Release OpenHarmony源码来解决此问题。

在foundation\distributeddatamgr\appdatamgr\frameworks\jskitsimpl\napi_preferences\include\napi_preferences.h文件中添加GetAll定义。

private:
    ...
    static napi_value GetAll(napi_env env, napi_callback_info info);
    ...
};

在foundation\distributeddatamgr\appdatamgr\frameworks\jskitsimpl\napi_preferences\src\napi_preferences.cpp文件中作如下改动:

  1. 引入头文件。

#include "js_utils.h"
  1. 在PreferencesProxy::Init中添加GetAll方法注入。

void PreferencesProxy::Init(napi_env env, napi_value exports)
{
    napi_property_descriptor descriptors[] = {
        ...
        DECLARE_NAPI_FUNCTION("getAll", GetAll),
        ...
    };
    ...
}
  1. 在PreferencesAysncContext : NapiAsyncProxy结构体中添加allElements字段定义。

struct PreferencesAysncContext : NapiAsyncProxy<PreferencesAysncContext>::AysncContext {
    ...
    std::map<std::string, PreferencesValue> allElements;
    ...
};
  1. 添加GetAll方法的实现。

//添加GetAll方法
napi_value PreferencesProxy::GetAll(napi_env env, napi_callback_info info)
{
    NapiAsyncProxy<PreferencesAysncContext> proxy;
    proxy.Init(env, info);
    std::vector<NapiAsyncProxy<PreferencesAysncContext>::InputParser> parsers;
    proxy.ParseInputs(parsers);
    return proxy.DoAsyncWork(
        "GetAll",
        [](PreferencesAysncContext *asyncContext) {
            PreferencesProxy *obj = reinterpret_cast<PreferencesProxy *>(asyncContext->boundObj);
            asyncContext->allElements = obj->value_->GetAll();
            return OK;
        },
        GetAllExecute);
}
​
//补充GetAllExecute方法
int32_t GetAllExecute(PreferencesAysncContext *asyncContext, napi_value &output)
{   
    LOG_ERROR("PreferencesProxy::GetAllExecute start");
    if (napi_create_object(asyncContext->env, &output) != napi_ok) {
        LOG_ERROR("PreferencesProxy::GetAll creat object failed");
        return ERR;
    }
    napi_value jsVal = nullptr;
    for (const auto &[key, value] : asyncContext->allElements) {
        PreferencesValue val = value;
        if (val.IsBool()) {
            jsVal = JSUtils::Convert2JSValue(asyncContext->env, (bool)val);
            if (nullptr == jsVal) {
                LOG_ERROR("PreferencesProxy::GetAll get property bool failed");
                return ERR;
            }
            if (napi_set_named_property(asyncContext->env, output, key.c_str(), jsVal) != napi_ok) {
                LOG_ERROR("PreferencesProxy::GetAll set property bool failed");
                return ERR;
            }
        } else if (val.IsDouble()) {
            jsVal = JSUtils::Convert2JSValue(asyncContext->env, (double)val);
            if (nullptr == jsVal) {
                LOG_ERROR("PreferencesProxy::GetAll get property double failed");
                return ERR;
            }
            if (napi_set_named_property(asyncContext->env, output, key.c_str(), jsVal) != napi_ok) {
                LOG_ERROR("PreferencesProxy::GetAll set property double failed");
                return ERR;
            }
        } else if (val.IsString()) {
            std::string tempStr = (std::string)val;
            jsVal = JSUtils::Convert2JSValue(asyncContext->env, tempStr);
            if (nullptr == jsVal) {
                LOG_ERROR("PreferencesProxy::GetAll get property string failed");
                return ERR;
            }
            if (napi_set_named_property(asyncContext->env, output, key.c_str(), jsVal) != napi_ok) {
                LOG_ERROR("PreferencesProxy::GetAll set property string failed");
                return ERR;
            }
        } else {
            LOG_ERROR("PreferencesProxy::GetAll other property ");
        }
    }
    LOG_ERROR("PreferencesProxy::GetAllExecute end");
    return OK;
}

按照以上步骤修改后,preferences.getAll()可以正常回调了。

5 定位过程

  1. 通过日志查看,在设备的3.2 Beta3版本中,getAll方法正常回调并打印所有键值的Object对象,而在设备的3.1 Release版本getAll方法回调失败,报错为不可调用,推测3.1 Release版本中没有定义getAll方法。

  2. 查看源码的napi_preferences.cpp文件,发现3.1 Release版本没有声明getAll方法,而3.2 Beta3版本声明了。参照3.2 Beta3版本,在3.1 Release版本中添加getAll的定义与方法实现。

6 知识分享

'@ohos.data.preferences'模块是从3.2 Beta1版本开始引入的,3.1 Relese版本对应的SDK文件中没有声明该模块。

Logo

社区规范:仅讨论OpenHarmony相关问题。

更多推荐