DEV Community

Cover image for [Learn HarmonyOS Next Knowledge Daily] JSVM-API, Hotfix, Object Unique Hash Value, Monitoring VPN Network Changes, etc.
kouwei qing
kouwei qing

Posted on

[Learn HarmonyOS Next Knowledge Daily] JSVM-API, Hotfix, Object Unique Hash Value, Monitoring VPN Network Changes, etc.

[Learn HarmonyOS Next Knowledge Daily] JSVM-API, Hotfix, Object Unique Hash Value, Monitoring VPN Network Changes, etc.

1. How to Use JSVM-API Interfaces to Create Multiple Engines for Executing JS Code and Destroy Them?

Create a new JS basic runtime environment and obtain a CoreID through the CreateJsCore method:

static napi_value CreateJsCore(napi_env env1, napi_callback_info info) {
  OH_LOG_INFO(LOG_APP, "JSVM CreateJsCore START");
  size_t argc = 1;
  napi_value argv[1];
  napi_get_cb_info(env1, info, &argc, argv, nullptr, nullptr);
  if (argc < 1) {
    OH_LOG_ERROR(LOG_APP, "JSVM CreateJsCore the number of params must be one");
    return nullptr;
  }
  g_napiEnvMap[ENVTAG_NUMBER] = env1;
  g_taskQueueMap[ENVTAG_NUMBER] = deque<Task *>{};
  // Store the callback function passed from the TS side in correspondence with env for subsequent calls
  napi_ref callFun;
  napi_create_reference(env1, argv[0], 1, &callFun);
  g_callBackMap[ENVTAG_NUMBER] = callFun;
  napi_value coreID = 0;
  {
    std::lock_guard<std::mutex> lock_guard(envMapLock);
    CreateArkJSContext();
    napi_create_uint32(env1, ENVTAG_NUMBER, &coreID);
    ENVTAG_NUMBER++;
  }
  OH_LOG_INFO(LOG_APP, "JSVM CreateJsCore END");
  return coreID;
}
Enter fullscreen mode Exit fullscreen mode

Execute JS code using the runtime environment corresponding to CoreID through the EvalUateJS method:

static napi_value EvalUateJS(napi_env env, napi_callback_info info) {
  OH_LOG_INFO(LOG_APP, "JSVM EvalUateJS START");
  size_t argc = 2;
  napi_value args[2] = {nullptr};
  napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
  uint32_t envId;
  napi_status status = napi_get_value_uint32(env, args[0], &envId);
  if (status != napi_ok) {
    OH_LOG_ERROR(LOG_APP, "EvalUateJS first param should be number");
    return nullptr;
  }

  if (g_envMap.count(envId) == 0 || g_envMap[envId] == nullptr) {
    OH_LOG_ERROR(LOG_APP, "EvalUateJS env is null");
    return nullptr;
  }
  std::string dataStr = napiValueToString(env, args[1]);
  napi_value res = nullptr;
  std::lock_guard<std::mutex> lock_guard(mutexLock);
  {
    // Open handle scope
    JSVM_HandleScope handlescope;
    OH_JSVM_OpenHandleScope(*g_envMap[envId], &handlescope);
    // Compile js script
    JSVM_Value sourcecodevalue;
    OH_JSVM_CreateStringUtf8(*g_envMap[envId], dataStr.c_str(), dataStr.size(), &sourcecodevalue);
    JSVM_Script script;
    OH_JSVM_CompileScript(*g_envMap[envId], sourcecodevalue, nullptr, 0, true, nullptr, &script);
    // Run js script
    JSVM_Value result;
    OH_JSVM_RunScript(*g_envMap[envId], script, &result);
    JSVM_ValueType type;
    OH_JSVM_Typeof(*g_envMap[envId], result, &type);
    OH_LOG_INFO(LOG_APP, "JSVM API TEST type: %{public}d", type);
    // Execute tasks in the current env event queue
    while (!g_taskQueueMap[envId].empty()) {
      auto task = g_taskQueueMap[envId].front();
      g_taskQueueMap[envId].pop_front();
      task->Run();
      delete task;
    }

    if (type == JSVM_STRING) {
      std::string stdResult = fromOHStringValue(*g_envMap[envId], result);
      napi_create_string_utf8(env, stdResult.c_str(), stdResult.length(), &res);
    } else if (type == JSVM_BOOLEAN) {
      bool ret = false;
      std::string stdResult;
      OH_JSVM_GetValueBool(*g_envMap[envId], result, &ret);
      ret ? stdResult = "true" : stdResult = "false";
      napi_create_string_utf8(env, stdResult.c_str(), stdResult.length(), &res);
    } else if (type == JSVM_NUMBER) {
      int32_t num;
      OH_JSVM_GetValueInt32(*g_envMap[envId], result, &num);
      std::string stdResult = std::to_string(num);
      napi_create_string_utf8(env, stdResult.c_str(), stdResult.length(), &res);
    } else if (type == JSVM_OBJECT) {
      JSVM_Value objResult;
      OH_JSVM_JsonStringify(*g_envMap[envId], result, &objResult);
      std::string stdResult = fromOHStringValue(*g_envMap[envId], objResult);
      napi_create_string_utf8(env, stdResult.c_str(), stdResult.length(), &res);
    }
    OH_JSVM_CloseHandleScope(*g_envMap[envId], handlescope);
  }
  OH_LOG_INFO(LOG_APP, "JSVM EvalUateJS END");
  return res;
}
Enter fullscreen mode Exit fullscreen mode

Release the runtime environment corresponding to CoreID through the ReleaseJsCore method:

static napi_value ReleaseJsCore(napi_env env1, napi_callback_info info) {
  OH_LOG_INFO(LOG_APP, "JSVM ReleaseJsCore START");
  size_t argc = 1;
  napi_value argv[1];
  napi_get_cb_info(env1, info, &argc, argv, nullptr, nullptr);
  if (argc < 1) {
    OH_LOG_ERROR(LOG_APP, "JSVM ReleaseJsCore the number of params must be one");
    return nullptr;
  }

  uint32_t coreEnvId;
  napi_status status = napi_get_value_uint32(env1, argv[0], &coreEnvId);
  if (status != napi_ok) {
    OH_LOG_ERROR(LOG_APP, "JSVM CreateJsCore napi_get_value_uint32 faild");
    return nullptr;
  }
  if (g_envMap.count(coreEnvId) == 0 ) {
    OH_LOG_ERROR(LOG_APP, "JSVM CreateJsCore not has env ");
    return nullptr;
  }
  if (g_envMap[coreEnvId] != nullptr) {
    std::lock_guard<std::mutex> lock_guard(envMapLock);
    OH_JSVM_CloseEnvScope(*g_envMap[coreEnvId], g_envScopeMap[coreEnvId]);
    g_envScopeMap.erase(coreEnvId);
    OH_JSVM_DestroyEnv(*g_envMap[coreEnvId]);
    g_envMap[coreEnvId] = nullptr;
    g_envMap.erase(coreEnvId);
    OH_JSVM_CloseVMScope(*g_vmMap[coreEnvId], g_vmScopeMap[coreEnvId]);
    g_vmScopeMap.erase(coreEnvId);
    OH_JSVM_DestroyVM(*g_vmMap[coreEnvId]);
    g_vmMap[coreEnvId] = nullptr;
    g_vmMap.erase(coreEnvId);
    delete [] g_callBackStructMap[coreEnvId];
    g_callBackStructMap[coreEnvId] = nullptr;
    g_callBackStructMap.erase(coreEnvId);
    napi_delete_reference(env1, g_callBackMap[coreEnvId]);
    g_callBackMap.erase(coreEnvId);
    g_taskQueueMap.erase(coreEnvId);
  }
  OH_LOG_INFO(LOG_APP, "JSVM ReleaseJsCore END");
  return nullptr;
}
Enter fullscreen mode Exit fullscreen mode

2. How to Handle Error Code 9568258: error:install releaseType not same?

After upgrading the IDE, package installation consistently prompts code:9568258, error:install releaseType not same, even after formatting the phone. Suspected to be caused by HSP packages, but there are 14 HSP packages in the private repository, making a full rebuild impractical. Are there alternative solutions?

Method 1: Uninstall the previous HAP on the local device before reinstalling.

Method 2: The issue arises from installing HAPs compiled with different SDK versions. Search for releasetype in the generated artifacts to check if the corresponding SDK value matches the current version.

3. How to Monitor and Determine VPN-Type Networks?

The VPN type can be obtained using the getNetCapabilities method to get bearerTypes. When the value of bearerTypes is 4, it indicates a VPN is in use. Sample code:

connection.getDefaultNet().then((netHandle: connection.NetHandle) => {
  connection.getNetCapabilities(netHandle).then((data: connection.NetCapabilities) => {
    const type: Number = data.bearerTypes[0];
    if (type === 4) {
      console.info('is vpn');
    }
  })
});
Enter fullscreen mode Exit fullscreen mode

4. How to Obtain a Unique Identifier (Hash Value) for an Object?

Use the util.getHash interface:

  • For the first-time acquisition, calculate the Hash value and save it to the object's Hash field (returns a random Hash value).
  • For subsequent acquisitions, retrieve and return the Hash value from the Hash field (the same object returns a consistent value across multiple calls).

5. Is It Recommended to Use bm quickfix to Create Repair Packages?

The reference document shows the command for installing quick-fix patches: bm quickfix -a -f /data/app/. Two questions arise:

  1. Documentation on how to create HQF files is missing.
  2. Is HQF a delta package between new and old versions? Scenario: Can the bm quickfix command be used to fix partial bugs during app runtime? Are there relevant reference documents?

Current Recommendation: Manual creation of HQF packages is not recommended. Instead, use the hot-reload capability: https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/ide-hot-reload-0000001527628941-V5?catalogVersion=V5

Top comments (0)