从网络下载的abc文件,通过napi_run_script_path接口执行的方法

通过网络下载的abc文件,保存到沙箱目录后,需要支持通过napi_run_script_path接口运行,这种场景,在现实中,经常会碰到,比如,过关游戏中,玩某一关卡时才下载对应的程序文件。

场景实现思路:

1.通过es2abc工具将ets文件生成abc文件,该工具为sdk自带工具,路径举例如下:

D:\Programs\sdk\HarmonyOS-NEXT-DP2\base\ets\build-tools\ets-loader\bin\ark\build-win\bin

如,将TestClass.ets文件生成TestClass.abc文件。

在命令行中,执行./es2abc.exe TestClass.ets指令,在工具目录下,就会生成对应的abc文件。

2.将abc文件放到工程的src/main/resources/rawfile目录下,代码中将该文件拷贝一份到应用的沙箱路径下,以此来模拟从网络上下载abc文件的过程。

3.需要配置ohos.permission.RUN_DYN_CODE权限,首先,在src/main/module.json5文件上添加该权限(requestPermissions项中):

...... 
"deviceTypes": [ 
  "phone" 
], 
"requestPermissions": [ 
  { 
    "name" : "ohos.permission.RUN_DYN_CODE", 
    "reason": "$string:reason", 
    "usedScene": { 
      "abilities": [ 
        "FormAbility" 
      ], 
      "when":"always" 
    } 
  } 
], 
"deliveryWithInstall": true, 
......

其次,在代码中,是该权限起作用。

4.通过verifyAbc文件来验证abc文件合法性,以便其将abc文件映射到el1目录下,如映射后的沙箱目录如下:

/data/storage/el1/bundle//abcs/data/storage/el2/base/haps/entry/files/TestClass.abc

5.通过首先的worker来调用napi_run_script_path接口

使用的OS能力相关的核心API

  •  requestPermissionsFromUser
  •  RestrictedWorker
  • getRawFileContent
  • napi_run_script_path
HarmonyOS
2024-06-11 20:24:37
浏览
收藏 0
回答 2
待解决
回答 2
按赞同
/
按时间
xbibi

1) 代码中申请权限:

aboutToAppear(): void { 
  // 申请权限 
  let atManager = abilityAccessCtrl.createAtManager(); 
  try { 
    let context: Context = getContext(this) as common.UIAbilityContext; 
    atManager.requestPermissionsFromUser(context, ["ohos.permission.RUN_DYN_CODE"]).then((data) => { 
      console.info("data:" + JSON.stringify(data)); 
      console.info("data permissions:" + data.permissions); 
      console.info("data authResults:" + data.authResults); 
      if (data.authResults[0] == 0) { 
        hilog.info(0x0000, 'testTag', 'Permission ok'); 
        this.isPermission = true; 
      } else { 
        hilog.info(0x0000, 'testTag', 'No Permission'); 
      }   
    }).catch((err: BusinessError) => { 
      hilog.info(0x0000, 'testTag', 'Permission error'); 
      console.info("data:" + JSON.stringify(err)); 
      return; 
    }) 
  } catch(err) { 
    console.log(`catch err->${JSON.stringify(err)}`); 
    return; 
  } 
}

2) 目录网路abc文件下载到沙箱目录:

WriteSanboxFile():void { 
  this.context.resourceManager.getRawFileContent(this.inFile, (err: BusinessError, data: Uint8Array) => { 
    if (err != null) { 
      console.error(`compressFile open xxx.zip failed: ${err.message}`) 
    } else { 
      let sandboxPath = this.context.filesDir; 
      let filePath = sandboxPath + "/" + this.inFile; 
      fs.access(filePath).then((res: boolean) => { 
        if (res) { 
          console.info("file exists"); 
        } else { 
          console.info("file not exists"); 
        } 
      }).catch((err: BusinessError) => { 
        console.error("access failed with error message: " + err.message + ", error code: " + err.code); 
      }); 
      fs.listFile(sandboxPath, {recursion: true}).then((filenames: Array<string>) => { 
        console.info("listFile succeed"); 
        for (let i = 0; i < filenames.length; i++) { 
          console.info("fileName: %s", filenames[i]); 
        } 
      }).catch((err: BusinessError) => { 
        console.error("list file failed with error message: " + err.message + ", error code: " + err.code); 
      }); 
      console.log(filePath); 
      this.runFilePath = '/abcs' + filePath; 
      let file: fileIo.File = fs.openSync(filePath, fs.OpenMode.CREATE | fs.OpenMode.READ_WRITE); 
      fs.writeSync(file.fd, data.buffer); 
      fs.close(file.fd); 
    } 
  }) 
}

3) 验证文件,以便映射到el1目录下:

VerifyABCFileHandle():void { 
  let paths : Array<string> = ['/data/storage/el2/base/haps/entry/files/TestClass.abc'] 
  try { 
    bms.verifyAbc(paths, true, (err, data) => { 
      if (err != null) { 
        console.info(" VerfyCallback result err: " + JSON.stringify(err) + ", code: " + err.code + ", msg: " + err.message); 
        return; 
      } else { 
        console.info(" VerfyCallback result err is null."); 
      } 
      if (data != null) { 
        console.info(" VerfyCallback result data: " + JSON.stringify(data)); 
      } else { 
        console.info(" VerfyCallback result data is null."); 
     } 
     this.isVerifyAbcSuccess = true; 
    }); 
  } catch (err) { 
    console.info(" VerfyCallback catch err: " + JSON.stringify(err) + ", code: " + err.code + ", msg: " + err.message); 
  } 
}

4) 通过受限worker调用abc文件:

const workerStageModel01 = new worker.RestrictedWorker('entry/ets/workers/Worker.ets', {name:"first worker in Stage model"}); 
workerStageModel01.postMessage(this.runFilePath);

5) Native C++层实现:

static napi_value JsRunScript(napi_env env, napi_callback_info info) { 
  size_t argc = 1; 
  napi_value args[1] = {nullptr}; 
 
  napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); 
 
  char buf[256] = {0}; 
  size_t result = 0; 
  napi_get_value_string_latin1(env, args[0], buf, 256, &result); 
 
  OH_LOG_INFO(LOG_APP, "jscript=%{public}s, result:%{public}zu", buf, result); 
  napi_value run_result; 
 
  napi_status status = napi_run_script_path(env, buf, &run_result); 
  if (status != napi_ok) { 
    OH_LOG_INFO(LOG_APP, "napi_run_script_path failed:%{public}d", status); 
  } else { 
    OH_LOG_INFO(LOG_APP, "napi_run_script_path success"); 
  } 
 
  return nullptr; 
}

实现效果

手机上执行结果如下:

分享
微博
QQ
微信
回复
2024-06-12 16:59:09
wx65e818bb61ffe

楼主 TestClass代码可以提供一下么, 还得还不是太懂

分享
微博
QQ
微信
回复
5天前
相关问题
如何使用接口下载文件
682浏览 • 1回复 待解决
以指定用户名执行 docker run 问题
1076浏览 • 1回复 待解决
如何通过AOP统计方法执行时间
238浏览 • 1回复 待解决
怎么DataAbilityHelper排除.flac文件?
3599浏览 • 1回复 待解决
如何官方下载鸿蒙os SDK ?
5581浏览 • 1回复 待解决
如何显示通过网络加载图片?
1143浏览 • 1回复 待解决
Native如何通过napi获取ArrayBuffer?
1811浏览 • 1回复 待解决