diff --git a/ohos/AdvancedAPI_OHOS/.babelrc b/ohos/AdvancedAPI_OHOS/.babelrc new file mode 100644 index 0000000000..f33928bb09 --- /dev/null +++ b/ohos/AdvancedAPI_OHOS/.babelrc @@ -0,0 +1,22 @@ +{ + "presets": [ + [ + "@babel/preset-env", + { + "modules":false, + "targets":{ + "chrome":"73", + "node":"16" + } + } + ] + ], + "plugins": [ + [ + "@babel/plugin-proposal-decorators", + { + "legacy": true + } + ] + ] +} \ No newline at end of file diff --git a/ohos/AdvancedAPI_OHOS/.eslintignore b/ohos/AdvancedAPI_OHOS/.eslintignore new file mode 100644 index 0000000000..3e22129247 --- /dev/null +++ b/ohos/AdvancedAPI_OHOS/.eslintignore @@ -0,0 +1 @@ +/dist \ No newline at end of file diff --git a/ohos/AdvancedAPI_OHOS/.eslintrc b/ohos/AdvancedAPI_OHOS/.eslintrc new file mode 100644 index 0000000000..8ae9b58d75 --- /dev/null +++ b/ohos/AdvancedAPI_OHOS/.eslintrc @@ -0,0 +1,154 @@ +{ + "parser": "babel-eslint", + + "extends": [ + "plugin:flowtype/recommended" + ], + + "plugins": [ + "flowtype" + ], + + "parserOptions": { + "ecmaVersion": 6, + "sourceType": "module" + }, + + "env": { + "es6": true, + "node": true, + "mocha": true + }, + "globals": { + "globalThis": false, + "AppStorage": true, + "requireAPI": true, + "getCachedElement": true, + "document": true + }, + + "rules": { + "flowtype/no-types-missing-file-annotation": 0, + "accessor-pairs": 2, + "arrow-spacing": [2, { "before": true, "after": true }], + "block-spacing": [2, "always"], + "brace-style": [2, "1tbs", { "allowSingleLine": true }], + "camelcase": [2, { "properties": "never" }], + "comma-dangle": [2, "only-multiline"], + "comma-spacing": [2, { "before": false, "after": true }], + "comma-style": [2, "last"], + "constructor-super": 2, + "curly": [2, "multi-line"], + "dot-location": [2, "property"], + "eol-last": 2, + "eqeqeq": [2, "allow-null"], + "generator-star-spacing": [2, { "before": true, "after": true }], + "handle-callback-err": [2, "^(err|error)$" ], + "indent": [2, 2, { "SwitchCase": 1 }], + "key-spacing": [2, { "beforeColon": false, "afterColon": true }], + "keyword-spacing": [2, { "before": true, "after": true }], + "new-cap": [2, { "newIsCap": true, "capIsNew": false }], + "new-parens": 2, + "no-array-constructor": 2, + "no-caller": 2, + "no-class-assign": 2, + "no-cond-assign": 2, + "no-const-assign": 2, + "no-control-regex": 2, + "no-debugger": 2, + "no-delete-var": 2, + "no-dupe-args": 2, + "no-dupe-class-members": 2, + "no-dupe-keys": 2, + "no-duplicate-case": 2, + "no-empty-character-class": 2, + "no-empty-pattern": 2, + "no-eval": 2, + "no-ex-assign": 2, + "no-extend-native": 2, + "no-extra-bind": 2, + "no-extra-boolean-cast": 2, + "no-extra-parens": [2, "functions"], + "no-fallthrough": 2, + "no-floating-decimal": 2, + "no-func-assign": 2, + "no-implied-eval": 2, + "no-inner-declarations": [2, "functions"], + "no-invalid-regexp": 2, + "no-irregular-whitespace": 2, + "no-iterator": 2, + "no-label-var": 2, + "no-labels": [2, { "allowLoop": false, "allowSwitch": false }], + "no-lone-blocks": 2, + "no-mixed-spaces-and-tabs": 2, + "no-multi-spaces": 2, + "no-multi-str": 2, + "no-multiple-empty-lines": [2, { "max": 1 }], + "no-native-reassign": 2, + "no-negated-in-lhs": 2, + "no-new-object": 2, + "no-new-require": 2, + "no-new-symbol": 2, + "no-new-wrappers": 2, + "no-obj-calls": 2, + "no-octal": 2, + "no-octal-escape": 2, + "no-path-concat": 2, + "no-proto": 2, + "no-redeclare": 2, + "no-regex-spaces": 2, + "no-return-assign": [2, "except-parens"], + "no-self-assign": 2, + "no-self-compare": 2, + "no-sequences": 2, + "no-shadow-restricted-names": 2, + "no-spaced-func": 2, + "no-sparse-arrays": 2, + "no-this-before-super": 2, + "no-throw-literal": 2, + "no-trailing-spaces": 2, + "no-undef": 2, + "no-undef-init": 2, + "no-unexpected-multiline": 2, + "no-unmodified-loop-condition": 2, + "no-unneeded-ternary": [2, { "defaultAssignment": false }], + "no-unreachable": 2, + "no-unsafe-finally": 2, + "no-unused-vars": [2, { "vars": "all", "args": "none" }], + "no-useless-call": 2, + "no-useless-computed-key": 2, + "no-useless-constructor": 2, + "no-useless-escape": 2, + "no-whitespace-before-property": 2, + "no-with": 2, + "one-var": [2, { "initialized": "never" }], + "padded-blocks": [2, "never"], + "quotes": [2, "single", {"avoidEscape": true, "allowTemplateLiterals": true}], + "semi": [2, "never"], + "semi-spacing": [2, { "before": false, "after": true }], + "space-before-blocks": [2, "always"], + "space-in-parens": [2, "never"], + "space-infix-ops": 2, + "space-unary-ops": [2, { "words": true, "nonwords": false }], + "spaced-comment": [2, "always", { "markers": ["global", "globals", "eslint", "eslint-disable", "*package", "!", ","] }], + "template-curly-spacing": [2, "never"], + "use-isnan": 2, + "valid-typeof": 2, + "wrap-iife": [2, "any"], + "yield-star-spacing": [2, "both"], + "yoda": [2, "never"], + + "no-var": 2, + "prefer-const": 2, + "object-curly-spacing": [2, "always", { + "objectsInObjects": false + }], + "array-bracket-spacing": [2, "never"] + }, + + "settings": { + "flowtype": { + "onlyFilesWithFlowAnnotation": true + } + } +} diff --git a/ohos/AdvancedAPI_OHOS/.gitignore b/ohos/AdvancedAPI_OHOS/.gitignore new file mode 100644 index 0000000000..673a34a791 --- /dev/null +++ b/ohos/AdvancedAPI_OHOS/.gitignore @@ -0,0 +1,11 @@ +dist +node_modules +src/qafApi/modules/Account/environment/SetMirror.js +package-lock.json +oh_modules +hvigor +.hvigor +.idea +oh-package-lock.json5 +local.properties +hvigorw \ No newline at end of file diff --git a/ohos/AdvancedAPI_OHOS/README.md b/ohos/AdvancedAPI_OHOS/README.md new file mode 100644 index 0000000000..43e1e333f8 --- /dev/null +++ b/ohos/AdvancedAPI_OHOS/README.md @@ -0,0 +1,22 @@ +### 编译生成js + +git clone下载源码,在根目录中执行: + +``` +npm install +``` + +然后使用如下命令打包生成一个js文件: + +``` +npm run build:advanced +``` + +### 生成har包或者hsp包 + +- 使用DevEco Studio打开project/advancedHsp工程,新建如下两个路径: + - project\advancedApiHsp\advanced_api_har\src\main\ets\utils\ + - project\advancedApiHsp\advanced_api_hsp\src\main\ets\utils\ +- 把生成的js文件dist/advancedapi.min.js复制到上述位置 +- 点击菜单: `Build` -- `Make All Modules`生成所有模块 +- har包生成在路径:advancedApiHsp\advanced_api_har\build\default\outputs\default中 diff --git a/ohos/AdvancedAPI_OHOS/build/build.js b/ohos/AdvancedAPI_OHOS/build/build.js new file mode 100644 index 0000000000..f53b8079aa --- /dev/null +++ b/ohos/AdvancedAPI_OHOS/build/build.js @@ -0,0 +1,141 @@ +const fs = require('fs') +const path = require('path') +const gzip = require('zlib').createGzip() +const rollup = require('rollup') + +const getConfig = require('./config') + +if (!fs.existsSync('dist')) { + fs.mkdirSync('dist') +} + +let isWatch = false +if (process.argv[3]) { + isWatch = process.argv[3] === '--watch' || process.argv[3] === '-w' +} + +// build specific package +if (process.argv[2]) { + build(process.argv[2]) +} else { + console.log('\nPlease specify the package you want to build. [native, runtime, browser, vue]') +} +build(process.argv[2]) + +function build (name) { + const pkgName = 'API' + console.log(`\n => start to build ${name} (${pkgName})\n`) + + if (isWatch) { + runRollupOnWatch(name) + return + } + + const config = getConfig({ name }) + const minifyConfig = getConfig({ minify: true, name }) + + return new Promise((resolve, reject) => { + runRollup(config).then(() => { + runRollup(minifyConfig).then(() => { + if(name==='advanced'){ + replaceFile(minifyConfig.output.file, + [ + /;import/g, + /from"/g, + /import{/g, + /}from/g, + /import"/g, + /";function/g + ] + , + [ + ';\nimport', + 'from "', + 'import {', + '} from', + 'import "', + '";\nfunction' + ]).then(()=>{ + zip(minifyConfig.output.file, resolve) + }) + }else{ + zip(minifyConfig.output.file, resolve) + } + }) + }) + }) +} + +function runRollup (config) { + return new Promise((resolve, reject) => { + rollup.rollup(config).then(bundle => { + bundle.write(config).then(() => { + report(config.output.file) + resolve() + }) + }) + }) +} + +function runRollupOnWatch (name) { + const config = getConfig({ name, isWatch }) + const watcher = rollup.watch(config) + watcher.on('event', event => { + switch (event.code) { + case 'STARTING': + console.log('checking rollup.watch version...') + break + case 'BUILD_START': + console.log('bundling...') + break + case 'BUILD_END': + break + case 'END': + console.info('compile jsBundle success...') + break + case 'ERROR': + console.error('ERROR: ', event.error) + break + } + }) +} + +function zip (filePath, callback) { + const read = fs.createReadStream(filePath) + const write = fs.createWriteStream(filePath + '.gz') + read.pipe(gzip).pipe(write).on('close', () => { + report(filePath + '.gz') + callback && callback() + }) +} + +function report (filePath) { + const size = (fs.statSync(filePath).size / 1024).toFixed(2) + 'KB' + const file = path.relative(process.cwd(), filePath) + console.log(` => write ${file} (${size})`) +} + +function replaceFile (filePath, sourceRegx, targetStr) { + return new Promise((resolve, reject) => { + fs.readFile(filePath, function (err, data) { + if (err) { + console.error(err) + reject() + return + } + let str = data.toString() + for (let i = 0; i < sourceRegx.length; i++) { + str = str.replace(sourceRegx[i], targetStr[i]) + } + fs.writeFile(filePath, str, function (err) { + if (err) { + console.error(err) + reject() + return + } + console.log('=> replaceFile success') + resolve() + }) + }) + }) +} \ No newline at end of file diff --git a/ohos/AdvancedAPI_OHOS/build/config.js b/ohos/AdvancedAPI_OHOS/build/config.js new file mode 100644 index 0000000000..e9ed5cc025 --- /dev/null +++ b/ohos/AdvancedAPI_OHOS/build/config.js @@ -0,0 +1,68 @@ +const { uglify } = require('rollup-plugin-uglify') +const bable = require('rollup-plugin-babel') +const path = require('path') +const resolve = require('rollup-plugin-node-resolve') +const commonjs = require('rollup-plugin-commonjs') + +function getConfig ({ isWatch = false, minify = false, name }) { + let packageName = '' + switch (name) { + case 'advanced': + packageName = 'advanced-api' + break + default: + packageName = 'advanced-api' + } + const frameworkBanner = 'if(typeof(global)===\'undefined\'){var global = globalThis}' + const frameworkfooter = '' + const configs = { + 'advanced-api': { + input: absolute('./src/advancedApi/index.js'), + output: { + name: 'ADVANCEDAPI', + file: absolute('dist/advancedapi.js'), + format: 'es', + banner: frameworkBanner, + footer: frameworkfooter || '' + }, + plugins: [] + } + } + + const opt = configs[packageName] + const config = { + input: opt.input, + output: { + name: opt.output.name, + file: minify ? opt.output.file.replace(/\.js$/, '.min.js') : opt.output.file, + format: opt.output.format, + banner: opt.output.banner || '', + footer: opt.output.footer || '' + }, + plugins: [ + bable({ + exclude: 'node_modules/**' + }), + commonjs(), + resolve() + ].concat(opt.plugins || []) + } + + if (minify) { + config.plugins.push(uglify({ + output: { + beautify: name!=='advanced' + } + })) + } else { + config.output.sourcemap = 'inline' + } + return config +} + +// get the absolute path +function absolute (str) { + return path.resolve(__dirname, '..', str) +} + +module.exports = getConfig diff --git a/ohos/AdvancedAPI_OHOS/jsconfig.json b/ohos/AdvancedAPI_OHOS/jsconfig.json new file mode 100644 index 0000000000..a178f9dcd0 --- /dev/null +++ b/ohos/AdvancedAPI_OHOS/jsconfig.json @@ -0,0 +1,5 @@ +{ + "compilerOptions": { + "experimentalDecorators": true + } +} \ No newline at end of file diff --git a/ohos/AdvancedAPI_OHOS/package.json b/ohos/AdvancedAPI_OHOS/package.json new file mode 100644 index 0000000000..55587102c7 --- /dev/null +++ b/ohos/AdvancedAPI_OHOS/package.json @@ -0,0 +1,37 @@ +{ + "name": "qafapi", + "version": "1.0.0", + "description": "QAF API", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1", + "build:advanced": "node build/build.js advanced", + "dev:advanced": "node build/build.js advanced --watch", + "build:web": "node build/build.js web", + "dev": "node build/build.js native --watch", + "lint": "eslint src", + "format": "eslint src --ext .js --fix" + }, + "author": "", + "license": "ISC", + "devDependencies": { + "@babel/core": "^7.14.6", + "@babel/plugin-proposal-decorators": "^7.10.5", + "@babel/preset-env": "^7.0.0", + "babel-eslint": "^10.0.3", + "eslint": "^6.6.0", + "eslint-plugin-flowtype": "^2.30.4", + "rollup": "^1.32.1", + "rollup-plugin-babel": "^4.4.0", + "rollup-plugin-buble": "^0.14.0", + "rollup-plugin-commonjs": "^10.1.0", + "rollup-plugin-node-resolve": "^5.2.0", + "rollup-plugin-typescript2": "^0.34.1", + "rollup-plugin-uglify": "^6.0.3", + "typescript": "^5.0.4" + }, + "dependencies": { + "js-base64": "^3.7.2", + "js-sha256": "^0.9.0", + "moment": "^2.29.3" + } +} diff --git a/ohos/AdvancedAPI_OHOS/project/advancedApiHsp/.gitignore b/ohos/AdvancedAPI_OHOS/project/advancedApiHsp/.gitignore new file mode 100644 index 0000000000..d2ff20141c --- /dev/null +++ b/ohos/AdvancedAPI_OHOS/project/advancedApiHsp/.gitignore @@ -0,0 +1,12 @@ +/node_modules +/oh_modules +/local.properties +/.idea +**/build +/.hvigor +.cxx +/.clangd +/.clang-format +/.clang-tidy +**/.test +/.appanalyzer \ No newline at end of file diff --git a/ohos/AdvancedAPI_OHOS/project/advancedApiHsp/AppScope/app.json5 b/ohos/AdvancedAPI_OHOS/project/advancedApiHsp/AppScope/app.json5 new file mode 100644 index 0000000000..d6acae6366 --- /dev/null +++ b/ohos/AdvancedAPI_OHOS/project/advancedApiHsp/AppScope/app.json5 @@ -0,0 +1,10 @@ +{ + "app": { + "bundleName": "com.example.advancedapihsp", + "vendor": "example", + "versionCode": 1000000, + "versionName": "1.0.0", + "icon": "$media:app_icon", + "label": "$string:app_name" + } +} diff --git a/ohos/AdvancedAPI_OHOS/project/advancedApiHsp/AppScope/resources/base/element/string.json b/ohos/AdvancedAPI_OHOS/project/advancedApiHsp/AppScope/resources/base/element/string.json new file mode 100644 index 0000000000..3a0b2ef125 --- /dev/null +++ b/ohos/AdvancedAPI_OHOS/project/advancedApiHsp/AppScope/resources/base/element/string.json @@ -0,0 +1,8 @@ +{ + "string": [ + { + "name": "app_name", + "value": "advancedApiHsp" + } + ] +} diff --git a/ohos/AdvancedAPI_OHOS/project/advancedApiHsp/AppScope/resources/base/media/app_icon.png b/ohos/AdvancedAPI_OHOS/project/advancedApiHsp/AppScope/resources/base/media/app_icon.png new file mode 100644 index 0000000000..a39445dc87 Binary files /dev/null and b/ohos/AdvancedAPI_OHOS/project/advancedApiHsp/AppScope/resources/base/media/app_icon.png differ diff --git a/ohos/AdvancedAPI_OHOS/project/advancedApiHsp/advanced_api_har/.gitignore b/ohos/AdvancedAPI_OHOS/project/advancedApiHsp/advanced_api_har/.gitignore new file mode 100644 index 0000000000..e2713a2779 --- /dev/null +++ b/ohos/AdvancedAPI_OHOS/project/advancedApiHsp/advanced_api_har/.gitignore @@ -0,0 +1,6 @@ +/node_modules +/oh_modules +/.preview +/build +/.cxx +/.test \ No newline at end of file diff --git a/ohos/AdvancedAPI_OHOS/project/advancedApiHsp/advanced_api_har/BuildProfile.ets b/ohos/AdvancedAPI_OHOS/project/advancedApiHsp/advanced_api_har/BuildProfile.ets new file mode 100644 index 0000000000..3a501e5dde --- /dev/null +++ b/ohos/AdvancedAPI_OHOS/project/advancedApiHsp/advanced_api_har/BuildProfile.ets @@ -0,0 +1,17 @@ +/** + * Use these variables when you tailor your ArkTS code. They must be of the const type. + */ +export const HAR_VERSION = '1.0.0'; +export const BUILD_MODE_NAME = 'debug'; +export const DEBUG = true; +export const TARGET_NAME = 'default'; + +/** + * BuildProfile Class is used only for compatibility purposes. + */ +export default class BuildProfile { + static readonly HAR_VERSION = HAR_VERSION; + static readonly BUILD_MODE_NAME = BUILD_MODE_NAME; + static readonly DEBUG = DEBUG; + static readonly TARGET_NAME = TARGET_NAME; +} \ No newline at end of file diff --git a/ohos/AdvancedAPI_OHOS/project/advancedApiHsp/advanced_api_har/Index.ets b/ohos/AdvancedAPI_OHOS/project/advancedApiHsp/advanced_api_har/Index.ets new file mode 100644 index 0000000000..8b8666f85f --- /dev/null +++ b/ohos/AdvancedAPI_OHOS/project/advancedApiHsp/advanced_api_har/Index.ets @@ -0,0 +1,2 @@ +import AdvancedAPI,{ as } from './src/main/ets/utils/advancedapi.min' +export { AdvancedAPI, as } \ No newline at end of file diff --git a/ohos/AdvancedAPI_OHOS/project/advancedApiHsp/advanced_api_har/build-profile.json5 b/ohos/AdvancedAPI_OHOS/project/advancedApiHsp/advanced_api_har/build-profile.json5 new file mode 100644 index 0000000000..e6773f9f5d --- /dev/null +++ b/ohos/AdvancedAPI_OHOS/project/advancedApiHsp/advanced_api_har/build-profile.json5 @@ -0,0 +1,31 @@ +{ + "apiType": "stageMode", + "buildOption": { + }, + "buildOptionSet": [ + { + "name": "release", + "arkOptions": { + "obfuscation": { + "ruleOptions": { + "enable": false, + "files": [ + "./obfuscation-rules.txt" + ] + }, + "consumerFiles": [ + "./consumer-rules.txt" + ] + } + }, + }, + ], + "targets": [ + { + "name": "default" + }, + { + "name": "ohosTest" + } + ] +} diff --git a/ohos/AdvancedAPI_OHOS/project/advancedApiHsp/advanced_api_har/consumer-rules.txt b/ohos/AdvancedAPI_OHOS/project/advancedApiHsp/advanced_api_har/consumer-rules.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/ohos/AdvancedAPI_OHOS/project/advancedApiHsp/advanced_api_har/hvigorfile.ts b/ohos/AdvancedAPI_OHOS/project/advancedApiHsp/advanced_api_har/hvigorfile.ts new file mode 100644 index 0000000000..4218707148 --- /dev/null +++ b/ohos/AdvancedAPI_OHOS/project/advancedApiHsp/advanced_api_har/hvigorfile.ts @@ -0,0 +1,6 @@ +import { harTasks } from '@ohos/hvigor-ohos-plugin'; + +export default { + system: harTasks, /* Built-in plugin of Hvigor. It cannot be modified. */ + plugins:[] /* Custom plugin to extend the functionality of Hvigor. */ +} diff --git a/ohos/AdvancedAPI_OHOS/project/advancedApiHsp/advanced_api_har/obfuscation-rules.txt b/ohos/AdvancedAPI_OHOS/project/advancedApiHsp/advanced_api_har/obfuscation-rules.txt new file mode 100644 index 0000000000..272efb6ca3 --- /dev/null +++ b/ohos/AdvancedAPI_OHOS/project/advancedApiHsp/advanced_api_har/obfuscation-rules.txt @@ -0,0 +1,23 @@ +# Define project specific obfuscation rules here. +# You can include the obfuscation configuration files in the current module's build-profile.json5. +# +# For more details, see +# https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/source-obfuscation-V5 + +# Obfuscation options: +# -disable-obfuscation: disable all obfuscations +# -enable-property-obfuscation: obfuscate the property names +# -enable-toplevel-obfuscation: obfuscate the names in the global scope +# -compact: remove unnecessary blank spaces and all line feeds +# -remove-log: remove all console.* statements +# -print-namecache: print the name cache that contains the mapping from the old names to new names +# -apply-namecache: reuse the given cache file + +# Keep options: +# -keep-property-name: specifies property names that you want to keep +# -keep-global-name: specifies names that you want to keep in the global scope + +-enable-property-obfuscation +-enable-toplevel-obfuscation +-enable-filename-obfuscation +-enable-export-obfuscation \ No newline at end of file diff --git a/ohos/AdvancedAPI_OHOS/project/advancedApiHsp/advanced_api_har/oh-package.json5 b/ohos/AdvancedAPI_OHOS/project/advancedApiHsp/advanced_api_har/oh-package.json5 new file mode 100644 index 0000000000..e00b65c81b --- /dev/null +++ b/ohos/AdvancedAPI_OHOS/project/advancedApiHsp/advanced_api_har/oh-package.json5 @@ -0,0 +1,9 @@ +{ + "name": "advanced_api_har", + "version": "1.0.0", + "description": "Please describe the basic information.", + "main": "Index.ets", + "author": "", + "license": "Apache-2.0", + "dependencies": {} +} diff --git a/ohos/AdvancedAPI_OHOS/project/advancedApiHsp/advanced_api_har/src/main/ets/components/MainPage.ets b/ohos/AdvancedAPI_OHOS/project/advancedApiHsp/advanced_api_har/src/main/ets/components/MainPage.ets new file mode 100644 index 0000000000..8bc3e27cce --- /dev/null +++ b/ohos/AdvancedAPI_OHOS/project/advancedApiHsp/advanced_api_har/src/main/ets/components/MainPage.ets @@ -0,0 +1,16 @@ +@Component +export struct MainPage { + @State message: string = 'Hello World'; + + build() { + Row() { + Column() { + Text(this.message) + .fontSize(50) + .fontWeight(FontWeight.Bold) + } + .width('100%') + } + .height('100%') + } +} diff --git a/ohos/AdvancedAPI_OHOS/project/advancedApiHsp/advanced_api_har/src/main/ets/utils/advancedapi.min.js b/ohos/AdvancedAPI_OHOS/project/advancedApiHsp/advanced_api_har/src/main/ets/utils/advancedapi.min.js new file mode 100644 index 0000000000..2d410ec514 --- /dev/null +++ b/ohos/AdvancedAPI_OHOS/project/advancedApiHsp/advanced_api_har/src/main/ets/utils/advancedapi.min.js @@ -0,0 +1,48 @@ +var global,_dec,_dec2,_dec3,_dec4,_dec5,_dec6,_dec7,_dec8,_dec9,_dec10,_dec11,_dec12,_dec13,_dec14,_class,_dec$1,_dec2$1,_class$1,_dec$2,_dec2$2,_dec3$1,_class$2;void 0===global&&(global=globalThis); +import abilityFeatureAbility from "@ohos.ability.featureAbility"; +import deviceInfo from "@ohos.deviceInfo"; +import display from "@ohos.display"; +import I18n from "@ohos.i18n"; +import abilityAccessCtrl from "@ohos.abilityAccessCtrl"; +import bluetooth from "@ohos.bluetooth"; +import geoLocationManager from "@ohos.geoLocationManager"; +import wifiManager from "@ohos.wifiManager"; +import window from "@ohos.window"; +import mapCommon from "@hms.core.map.mapCommon"; +import map from "@hms.core.map.map"; +import wantAgent from "@ohos.app.ability.wantAgent"; +import backgroundTaskManager from "@ohos.resourceschedule.backgroundTaskManager"; +import call from "@ohos.telephony.call"; +import http from "@ohos.net.http"; +import request$1 from "@ohos.request"; +import fs from "@ohos.file.fs"; +import photoAccessHelper from "@ohos.file.photoAccessHelper"; +import dataSharePredicates from "@ohos.data.dataSharePredicates"; +import bluetoothManager from "@ohos.bluetoothManager"; +import access from "@ohos.bluetooth.access"; +import ble from "@ohos.bluetooth.ble"; +import connection from "@ohos.bluetooth.connection"; +import promptAction from "@ohos.promptAction"; +import router from "@ohos.router"; +import wifi from "@ohos.wifi"; +import userIAM_userAuth from "@ohos.userIAM.userAuth"; +import prompt from "@ohos.prompt"; +import sensor from "@ohos.sensor"; +import contact from "@ohos.contact"; +import vibrator from "@ohos.vibrator"; +import inputMethod from "@ohos.inputMethod"; +import fileuri from "@ohos.file.fileuri"; +import wantConstant from "@ohos.ability.wantConstant"; +import bundleManager from "@ohos.bundle.bundleManager"; +import image from "@ohos.multimedia.image"; +import picker from "@ohos.file.picker"; +import media from "@ohos.multimedia.media"; +import audio from "@ohos.multimedia.audio"; +import avSession from "@ohos.multimedia.avsession"; +import cryptoFramework from "@ohos.security.cryptoFramework"; +import buffer from "@ohos.buffer"; +import util from "@ohos.util"; +import settings from "@ohos.settings"; +import scanCore from "@hms.core.scan.scanCore"; +import scanBarcode from "@hms.core.scan.scanBarcode"; +function _applyDecoratedDescriptor(o,a,e,t,r){var s={};return Object.keys(t).forEach(function(e){s[e]=t[e]}),s.enumerable=!!s.enumerable,s.configurable=!!s.configurable,("value"in s||s.initializer)&&(s.writable=!0),s=e.slice().reverse().reduce(function(e,t){return t(o,a,e)||e},s),r&&void 0!==s.initializer&&(s.value=s.initializer?s.initializer.call(r):void 0,s.initializer=void 0),void 0===s.initializer?(Object.defineProperty(o,a,s),null):s}function _defineProperty(e,t,o){return(t=_toPropertyKey(t))in e?Object.defineProperty(e,t,{value:o,enumerable:!0,configurable:!0,writable:!0}):e[t]=o,e}function _toPrimitive(e,t){if("object"!=typeof e||!e)return e;var o=e[Symbol.toPrimitive];if(void 0===o)return("string"===t?String:Number)(e);if("object"!=typeof(o=o.call(e,t||"default")))return o;throw new TypeError("@@toPrimitive must return a primitive value.")}function _toPropertyKey(e){return"symbol"==typeof(e=_toPrimitive(e,"string"))?e:e+""}let context=abilityFeatureAbility.getContext();function initContextOnStageModel(e){(context=e).startAbilityForResult||(context.startAbilityForResult=context.startAbility),context.getAbilityInfo=function(){return new Promise((e,t)=>{try{e(this.abilityInfo)}catch(e){t(e)}})},context.getFilesDir=function(){return new Promise((e,t)=>{try{e(this.filesDir)}catch(e){t(e)}})},context.getCacheDir=function(){return new Promise((e,t)=>{try{e(this.cacheDir)}catch(e){t(e)}})}}class AbilityBase{static getAbilityInfo(){return new Promise((t,o)=>{this.hasAbilityInfo?t(this.abilityInfo):context.getAbilityInfo().then(e=>{this.hasAbilityInfo=!0,this.abilityInfo=e,console.log("[QAFAPI] getAbilityInfo successful. "),t(e)}).catch(e=>{console.error("[QAFAPI] getAbilityInfo failed. Cause: "+JSON.stringify(e)),o(e)})})}}_defineProperty(AbilityBase,"abilityInfo",{}),_defineProperty(AbilityBase,"hasAbilityInfo",!1);class DeivceBase{static getDeviceInfo(){return deviceInfo}}class DisplayBase{static ohosGetDisplay(){let e=null;try{e=display.getDefaultDisplaySync()}catch(e){console.error("[QAFAPI] display error message: "+JSON.stringify(e))}return e}}class ASDevice{getSystemInfoSync(){var{brand:e,productModel:t,osFullName:o,deviceType:a,udid:r,sdkApiVersion:s}=DeivceBase.getDeviceInfo(),i=o.split("-")[0],n=i,c=o.split("-")[1],l=c,d=I18n.System.getSystemLanguage(),{rotation:h,densityPixels:u}=p=DisplayBase.ohosGetDisplay(),{width:p,height:f}=p,p=Math.round(p/u),f=Math.round(f/u),h=1===h||3===h?"landscape":"portrait",{signatureInfo:A,versionName:g,versionCode:m,appInfo:y}=globalThis.bundleInfoForSelf,y=context.resourceManager.getStringSync(y.labelId),A=A.appId,S=context.config.language,{width:v,height:C,top:P}=null==(v=globalThis.lastWindow.getWindowProperties())?void 0:v.windowRect,{isFullScreen:E,isLayoutFullScreen:b}=globalThis.lastWindow.getWindowProperties(),I=globalThis.lastWindow.getWindowAvoidArea(window.AvoidAreaType.TYPE_SYSTEM),I=Math.round(((null==I||null==(I=I.topRect)?void 0:I.height)||0)/u),E=E||b?Math.round(C/u):Math.round((C+I)/u),P=Math.round(P/u),b={deviceType:a,deviceBrand:e,brand:e,deviceModel:t,platform:n,model:t,deviceOrientation:h,devicePixelRatio:u,pixelRatio:u,system:o,osName:n,osVersion:l,version:l,osLanguage:d,language:d,ohosAPILevel:s,romName:i,romVersion:c,appId:A,appName:y,appVersion:g,appVersionCode:m,appLanguage:S,screenWidth:p,screenHeight:f,windowWidth:Math.round(v/u),windowHeight:Math.round(C/u),windowTop:P,windowBottom:E,statusBarHeight:I};return r&&(b.deviceId=r),b}getDeviceInfo(){console.debug("[AdvancedAPI] start ASDevice getDeviceInfo");var{brand:e,productModel:t,osFullName:o,deviceType:a,osFullName:r,udid:s}=DeivceBase.getDeviceInfo(),i=e,n=t,r=r.split("-")[0],{densityPixels:c,rotation:l}=DisplayBase.ohosGetDisplay(),r={platform:r,deviceBrand:i,deviceModel:t,deviceType:a,deviceOrientation:1===l||3===l?"landscape":"portrait",devicePixelRatio:c,system:o,brand:e,model:n};return s&&(r.deviceId=s),r}getWindowInfo(){console.debug("[AdvancedAPI] start ASDevice getWindowInfo");var e=(t=DisplayBase.ohosGetDisplay()).densityPixels,{width:t,height:o}=t,{width:a,height:r,top:s}=null==(a=globalThis.lastWindow.getWindowProperties())?void 0:a.windowRect,{isFullScreen:i,isLayoutFullScreen:n}=globalThis.lastWindow.getWindowProperties(),c=globalThis.lastWindow.getWindowAvoidArea(window.AvoidAreaType.TYPE_SYSTEM),c=Math.round(((null==c||null==(c=c.topRect)?void 0:c.height)||0)/e),i=i||n?Math.round(r/e):Math.round((r+c)/e),s=Math.round(s/e),a=Math.round(a/e),r=Math.round(r/e);return{pixelRatio:e,screenWidth:Math.round(t/e),screenHeight:Math.round(o/e),windowWidth:a,windowHeight:r,windowTop:s,windowBottom:i,statusBarHeight:c}}getAppBaseInfo(){console.debug("[AdvancedAPI] start ASDevice getAppBaseInfo");var{signatureInfo:e,versionName:t,versionCode:o,appInfo:a}=globalThis.bundleInfoForSelf,r=a.debug,a=context.resourceManager.getStringSync(a.labelId),e=e.appId,s=context.config.language,i=(Environment.envProp("colorMode",-1),AppStorage.get("colorMode"));return{appId:e,appName:a,appVersion:t,appVersionCode:o,appLanguage:s,enableDebug:r,theme:0===i?"light":1===i?"dark":"auto"}}getAppAuthorizeSetting(){console.debug("[AdvancedAPI] start ASDevice getAppAuthorizeSetting");var e=abilityAccessCtrl.createAtManager(),t=globalThis.bundleInfoForSelf.appInfo.accessTokenId,o=e=>-1===e?"denied":0===e?"authorized":"config error";let a="not determined";try{a=o(a=e.checkAccessTokenSync(t,"ohos.permission.WRITE_IMAGEVIDEO"))}catch(e){console.debug("[AdvancedAPI] ASDevice getAppAuthorizeSetting checkAccessToken album fail")}let r="not determined";try{r=o(r=e.checkAccessTokenSync(t,"ohos.permission.USE_BLUETOOTH"))}catch(e){console.debug("[AdvancedAPI] ASDevice getAppAuthorizeSetting checkAccessToken bluetooth fail")}let s="not determined";try{s=o(s=e.checkAccessTokenSync(t,"ohos.permission.CAMERA"))}catch(e){console.debug("[AdvancedAPI] ASDevice getAppAuthorizeSetting checkAccessToken camera fail")}let i="not determined";try{i=o(i=e.checkAccessTokenSync(t,"ohos.permission.LOCATION"))}catch(e){console.debug("[AdvancedAPI] ASDevice getAppAuthorizeSetting checkAccessToken location fail")}let n="not determined";try{n=0===e.checkAccessTokenSync(t,"ohos.permission.APPROXIMATELY_LOCATION")?"full":"reduced"}catch(e){console.debug("[AdvancedAPI] ASDevice getAppAuthorizeSetting checkAccessToken locationAccuracy fail")}let c="not determined";try{c=o(c=e.checkAccessTokenSync(t,"ohos.permission.MICROPHONE"))}catch(e){console.debug("[AdvancedAPI] ASDevice getAppAuthorizeSetting checkAccessToken microphone fail")}let l="not determined";try{l=o(l=e.checkAccessTokenSync(t,"ohos.permission.NOTIFICATION_CONTROLLER"))}catch(e){console.debug("[AdvancedAPI] ASDevice getAppAuthorizeSetting checkAccessToken notification fail")}let d="not determined";try{d=o(d=e.checkAccessTokenSync(t,"ohos.permission.READ_CALENDAR"))}catch(e){console.debug("[AdvancedAPI] ASDevice getAppAuthorizeSetting checkAccessToken phoneCalendar fail")}return{albumAuthorized:a,bluetoothAuthorized:r,cameraAuthorized:s,locationAuthorized:i,locationAccuracy:n,microphoneAuthorized:c,notificationAuthorized:l,phoneCalendarAuthorized:d}}getSystemSetting(){let e,t,o,a,r;try{e=!(2!==(e=bluetooth.getState())&&5!==e)}catch(e){console.error("errCode:"+e.code+",errMessage:"+e.message),a=e.message}try{t=geoLocationManager.isLocationEnabled()}catch(e){console.error("errCode:"+e.code+",errMessage:"+e.message),r=e.message}try{o=wifiManager.isWifiActive()}catch(e){console.error("errCode:"+e.code+",errMessage:"+e.message)}var s=DisplayBase.ohosGetDisplay().rotation;return{bluetoothEnabled:e,bluetoothError:a,locationEnabled:t,locationError:r,wifiEnabled:o,deviceOrientation:1===s||3===s?"landscape":"portrait"}}openAppAuthorizeSetting(){var e={bundleName:"com.huawei.hmos.settings",abilityName:"com.huawei.hmos.settings.MainAbility",uri:"application_info_entry",parameters:{pushParams:context.applicationInfo.name}};return context.startAbilityForResult(e)}}let ErrorCode$1={SHARE_INSTALLED_ERROR:-1001,SUCCESS:0,COMMON_ERROR:200,USER_REJECT:201,PARAMETER_ERROR:202,SERVICE_UNAVIALABLE:203,SERVICE_TIMEOUT:204,NOT_SUPPORT_SERVICE_COUNTRY:205,NOT_IN_WHITE_LIST:206,SYSTEM_PERMISSION_DENIAL:207,IO_ERROR:300,FILE_NOT_FOUND:301,FILE_EXIST:302,FILE_EXTENSION_NOT_EXIST:303,FILE_PATH_NOT_LEGAL:304,WEB_PAGE_NOT_FOUND:404,QUICKAPP_IN_BACKGROUND:500,LOCATION_SWITCH_CLOSED:1e3,PAY_CHECKKEY_FAIL:1001,SIM_NOT_FOUND:1001,SIGNIN_AUTH_FAIL:1002,OPERATORS_GET_FAIL:1002,ALARM_SYSTEM_ERROR:1003,AGD_COMMON_ERROR:2001,WIDGET_NOT_SUPPORT:2001,CARD_CALL_QUICK_APP_CENTER_FAIL:2003,BI_REPORT_ERROR:4001,PAY_CANCEL_CODE:3e4,PAY_CERTIFICATION_CODE:30102},BLHErrorCode={OK:0,OTHER_ERRORS:200,NOT_INIT:1e4,NOT_AVAILABLE:10001,NO_DEVICE:10002,CONNECTION_FAIL:10003,NO_SERVICE:10004,NO_CHARACTERISTIC:10005,NO_CONNECTION:10006,PROPERTY_NOT_SUPPORT:10007,SYSTEM_ERROR:10008,SYSTEM_NOT_SUPPORT:10009,LOCATION_NOT_TURN_ON:10010,NO_SUCH_INTERFACE:10100,DEVICE_DOES_NOT_EXIST:10101,NOT_AVAILABLE_TIRAMISU:10102},WifiErrorCode={PASSWORD_ERROR:1e3,CONNECTION_TIMEOUT:1001,DUPLICATE_REQUEST:1002,WIFI_NOT_TURNED_ON:1003,GPS_NOT_TURNED_ON:1004,INVALID_SSID:1005};function dataToArray(e){return Array.isArray(e)?e:[e]}class Result{static success(e,t=!1,o=!1){return{method:"success",arguments:dataToArray(e),ignoreComplete:t,ifKeepAlive:o}}static fail(e,t=!1,o=!1){return{method:"fail",arguments:dataToArray(e),ignoreComplete:t,ifKeepAlive:o}}static cancel(e,t=!1,o=!1){return{method:"cancel",arguments:dataToArray(e),ignoreComplete:t,ifKeepAlive:o}}static callback(e,t=!1,o=!1){return{method:"callback",arguments:dataToArray(e),ignoreComplete:t,ifKeepAlive:o}}static destroy(e,t=!1,o=!1){return{method:"destroy",arguments:dataToArray(e),ignoreComplete:t,ifKeepAlive:o}}}class ASLocation{constructor(){this.locationChangeCallbacks=[],this.locationChangeErrorCallback=(e,t)=>{},this.bothCallback=(t,e)=>{if(e)this.locationChangeErrorCallback({errMsg:e[2].arguments[0],errCode:e[2].arguments[1]});else for(let e=0;e{var o=t.authResults,a=t.dialogShownResults,r=o.length;for(let e=0;e{var e;return console.debug("[AdvancedAPI] current location: %s",JSON.stringify(t)),"gcj02"===(null==s?void 0:s.type)?(e={latitude:t.latitude,longitude:t.longitude},map.convertCoordinate(mapCommon.CoordinateType.WGS84,mapCommon.CoordinateType.GCJ02,e).then(e=>(t.latitude=e.latitude,t.longitude=e.longitude,Promise.resolve(t))).catch(e=>(console.debug("[AdvancedAPI] promise, convertCoordinate: error= %s",JSON.stringify(e)),Promise.reject([[e.message,ErrorCode$1.SERVICE_UNAVIALABLE]])))):Promise.resolve(t)}).catch(e=>(console.debug("[AdvancedAPI] promise, getCurrentLocation: error= %s",JSON.stringify(e)),Promise.reject([[e.message,ErrorCode$1.SERVICE_UNAVIALABLE]])))}catch(e){return console.error("[AdvancedAPI] errCode:"+e.code+",errMessage:"+e.message),Promise.reject([[e.message,ErrorCode$1.SERVICE_UNAVIALABLE]])}})}onLocationChange(e){console.debug("[AdvancedAPI] start ASLocation onLocationChange"),this.locationChangeCallbacks.push(e)}offLocationChange(e){console.debug("[AdvancedAPI] start ASLocation offLocationChange"),e?0<=(e=this.locationChangeCallbacks.indexOf(e))&&this.locationChangeCallbacks.splice(e,1):this.locationChangeCallbacks=[]}onLocationChangeError(e){console.debug("[AdvancedAPI] start ASLocation onLocationChangeError"),this.locationChangeErrorCallback=e}offLocationChangeError(){console.debug("[AdvancedAPI] start ASLocation offLocationChangeError"),this.locationChangeErrorCallback=(e,t)=>{}}startLocationUpdate(){console.debug("[AdvancedAPI] start ASLocation startLocationUpdate");var e=abilityAccessCtrl.createAtManager();try{return e.requestPermissionsFromUser(context,["ohos.permission.APPROXIMATELY_LOCATION","ohos.permission.LOCATION"]).then(t=>{var o=t.authResults,a=o.length;for(let e=0;e{var o=t.authResults,a=o.length;for(let e=0;e{e={wants:[{bundleName:e.bundleName,abilityName:e.name}],operationType:wantAgent.OperationType.START_ABILITY,requestCode:0,wantAgentFlags:[wantAgent.WantAgentFlags.UPDATE_PRESENT_FLAG]},wantAgent.getWantAgent(e).then(e=>backgroundTaskManager.startBackgroundRunning(context,backgroundTaskManager.BackgroundMode.LOCATION,e)).then(()=>{console.debug("[AdvancedAPI] start bg operation succeeded")}).catch(e=>{console.error("[AdvancedAPI] start bg operation failed Cause: "+e)})});try{return geoLocationManager.on("locationChange",{priority:515,scenario:768,timeInterval:0,distanceInterval:0,maxAccuracy:0},this.bothCallback),Promise.resolve("SUCCESS")}catch(e){return Promise.reject([[e.message,e.code]])}})}catch(e){return Promise.reject([["startLocationUpdateBackground failed",ErrorCode$1.COMMON_ERROR]])}}stopLocationUpdate(e){console.debug("[AdvancedAPI] start ASLocation stopLocationUpdate"),backgroundTaskManager.stopBackgroundRunning(context).then(()=>{console.debug("[AdvancedAPI] stop operation succeeded")}).catch(e=>{console.error("[AdvancedAPI] stop operation fail cause: "+JSON.stringify(e))});try{return geoLocationManager.off("locationChange"),Promise.resolve("SUCCESS")}catch(e){return Promise.reject([["stopLocationUpdate failed",ErrorCode$1.COMMON_ERROR]])}}}class ASPhone{makePhoneCall(e){return e&&e.phoneNumber&&"string"==typeof e.phoneNumber&&""!==e?call.makeCall(e.phoneNumber):new Promise((e,t)=>{t(["param is invalid.",ErrorCode$1.PARAMETER_ERROR])})}}function isMac(e){return/^[A-Fa-f\d]{2}:[A-Fa-f\d]{2}:[A-Fa-f\d]{2}:[A-Fa-f\d]{2}:[A-Fa-f\d]{2}:[A-Fa-f\d]{2}$/.test(e)}function isUuid(e){return/^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$/.test(e)}function isLower(e){return e===e.toLowerCase()}function isNumber(e){return"number"==typeof e&&!Number.isNaN(e)&&Number.isFinite(e)}function isString(e){return"string"==typeof e}function isBoolean(e){return"boolean"==typeof e}function isFunction(e){return"function"==typeof e}function isArrayBuffer(e){return"[object ArrayBuffer]"===Object.prototype.toString.call(e)}function isNull(e){return null===e}function isUndefined(e){return void 0===e}function isArray(e){return Array.isArray(e)}function isHexcolor(e){return/^#[0-9a-fA-F]{6}$/i.test(e)||/^#[0-9a-fA-F]{3}$/i.test(e)}function checkDataType(t,e,o,a){let r=!1;try{if(e&&(isNull(t)||isUndefined(t)))throw new Error("The param data is required");if(!isString(o)&&!isArray(o))throw new Error("The param dataType should be a String or an Array");if(!isNull(a)&&!isUndefined(a)&&!isFunction(a))throw new Error("If customCheck exist,it should be a Function");if(!e&&(isNull(t)||isUndefined(t)))return!0;isString(o)?r=checkSingleDataType(t,o):isArray(o)&&(r=o.some(e=>checkSingleDataType(t,e))),r&&isFunction(a)&&(r=a(t))}catch(e){return console.log(e),!1}return r}function checkSingleDataType(e,t){let o=!1;switch(t){case"string":o=isString(e);break;case"number":o=isNumber(e);break;case"boolean":o=isBoolean(e);break;case"function":o=isFunction(e);break;case"arraybuffer":o=isArrayBuffer(e);break;case"array":o=isArray(e);break;case"hexcolor":o=isHexcolor(e);break;case"null":o=isNull(e);break;case"undefined":o=isUndefined(e);break;default:throw new Error("The param dataType is unsupport")}return o}class MediaLibraryBase{static getPermissions(){try{let e=["ohos.permission.SHORT_TERM_WRITE_IMAGEVIDEO"],t=abilityAccessCtrl.createAtManager();return new Promise(o=>{t.requestPermissionsFromUser(context,e).then(e=>{var t=e.authResults[0],e=e.dialogShownResults[0];o({perNum:t,dialogShownResults:e})})})}catch(e){console.error("[AdvancedAPI] getPermissions is fail!",JSON.stringify(e))}}static getMediaType(e){return photoAccessHelper.PhotoType[e]}static getFileKey(){return photoAccessHelper.PhotoKeys}static getMedia(){return photoAccessHelper.getPhotoAccessHelper(context)}static async createAsset(e,t,o){var a=o.split(".").pop().toString(),o=o.split(".").shift().toString();return e.createAsset(t,a,{title:o})}static closeAsset(e,o){return new Promise(t=>{e.close(o,e=>{t(void 0===e)})})}static getFd(e){return new Promise(t=>{e.open("rw").then(e=>{t(e)}).catch(()=>{t(!1)})})}}function switchInternalToHapSandBox(e){return e.startsWith("internal://bundle/")?e.replace("internal://bundle",context.bundleCodeDir):e.startsWith("internal://cache/")?e.replace("internal://cache",context.cacheDir):e.startsWith("internal://files/")?e.replace("internal://files",context.filesDir):e.startsWith("internal://preferences/")?e.replace("internal://preferences",context.preferencesDir):e.startsWith("internal://temp/")?e.replace("internal://temp",context.tempDir):e.startsWith("internal://database/")?e.replace("internal://database",context.databaseDir):e.startsWith("internal://distributedFiles/")?e.replace("internal://distributedFiles",context.distributedFilesDir):e}function switchHapSandBoxToInternal(e){return e.startsWith(context.bundleCodeDir)?e.replace(context.bundleCodeDir,"internal://bundle"):e.startsWith(context.cacheDir)?e.replace(context.cacheDir,"internal://cache"):e.startsWith(context.filesDir)?e.replace(context.filesDir,"internal://files"):e.startsWith(context.preferencesDir)?e.replace(context.preferencesDir,"internal://preferences"):e.startsWith(context.tempDir)?e.replace(context.tempDir,"internal://temp"):e.startsWith(context.databaseDir)?e.replace(context.databaseDir,"internal://database"):e.startsWith(context.distributedFilesDir)?e.replace(context.distributedFilesDir,"internal://distributedFiles"):e}function isFileUri(e){return e&&"string"==typeof e&&(e.startsWith("file://")||e.startsWith("datashare://"))}function isSandboxPath(e){return e&&"string"==typeof e&&(e.startsWith("/data/storage/")||e.startsWith("internal://"))}function getFdFromUriOrSandBoxPath(t){try{return fs.openSync(t,fs.OpenMode.READ_ONLY).fd}catch(e){console.info(`[AdvancedAPI] Can not get file from uri: ${t} `)}throw new Error("file is not exist")}async function getFileAssetFromUri(e){try{-1===(await MediaLibraryBase.getPermissions()).perNum&&console.debug("[AdvancedAPI] permission fail");var t=photoAccessHelper.getPhotoAccessHelper(context),o=new dataSharePredicates.DataSharePredicates,a=(console.debug(`[AdvancedAPI] getFileAssetFromUri uri: ${e} `),o.equalTo(photoAccessHelper.PhotoKeys.URI,e.toString()),{fetchColumns:[photoAccessHelper.PhotoKeys.URI,photoAccessHelper.PhotoKeys.PHOTO_TYPE,photoAccessHelper.PhotoKeys.SIZE,photoAccessHelper.PhotoKeys.DURATION,photoAccessHelper.PhotoKeys.WIDTH,photoAccessHelper.PhotoKeys.HEIGHT,photoAccessHelper.PhotoKeys.TITLE,photoAccessHelper.PhotoKeys.ORIENTATION],predicates:o}),r=await t.getAssets(a),s=(console.debug(`[AdvancedAPI] getFileAssetFromUri fetchResult: ${JSON.stringify(r)} `),await r.getFirstObject());return console.debug(`[AdvancedAPI] getFileAssetFromUri asset: ${JSON.stringify(s)} `),r.close(),s}catch(e){console.debug("[AdvancedAPI] getAsset is fail!,"+e)}}function pathToCache(e){try{var t=switchInternalToHapSandBox(e),o=t.slice(t.lastIndexOf("/")),a=context.cacheDir+o;return fs.copyFile(t,a,e=>{e&&console.info("[AdvancedAPI] Failed to copy: "+JSON.stringify(e))}),switchHapSandBoxToInternal(a)}catch(e){console.error("[AdvancedAPI] to copy: "+JSON.stringify(e))}}async function saveMedia(e,t,o,a){try{var r=photoAccessHelper.getPhotoAccessHelper(context),s=t.split(".").pop().toString(),i=[{title:t.split(".").shift().toString().toString(),fileNameExtension:s.toString(),photoType:e}],n=[o.toString()],c=(await r.showAssetsCreationDialog(n,i))[0],l=fs.openSync(c,fs.OpenMode.READ_WRITE);return await fs.write(l.fd,a),fs.closeSync(l),c}catch(e){console.error("[AdvancedAPI] saveMedia is fail!: "+JSON.stringify(e))}}function arrayBufferToBase64(e){return requireAPI("ASBuffer").arrayBufferToBase64(e)}let errMsgMap=new Map([[401,"Parameter error"],[201,"Permission denied"],[2300003,"URL using bad/illegal format or missing URL"],[2300006,"Could not resolve host name"],[2300007,"Couldn not connect to server"],[2300009,"Access denied to remote resource"],[2300023,"Failed writing received data to disk/application"],[2300025,"Upload failed"],[2300026,"Failed to open/read local data from file/application"],[2300028,"Timeout was reached"],[2300073,"Remote file already exists"],[2300078,"Remote file not found"],[2300999,"Unknown Other Error"]]);class ASRequest{request(e){return console.debug("[AdvancedAPI] ASRequest request"),new RequestTask(e)}uploadFile(e){return console.debug("[AdvancedAPI] ASRequest uploadFile : %s",JSON.stringify(e)),new UploadTask(e)}downloadFile(e){return console.debug("[AdvancedAPI] ASRequest downloadFile %s",JSON.stringify(e)),new DownloadTask(e)}}class RequestTask{constructor(s){let{url:i,header:a,method:n="GET",timeout:c,responseType:l,enableCache:d}=s||{},h=(s||{}).data,{success:u,fail:p,complete:f}=s||{};if(this.abortFlag=!1,this.fail=p,this.complete=f,this.httpRequest=http.createHttp(),this.headersCallback=new Map,s){let e=!1;for(var A in a)if("content-type"===A.toLowerCase()){a[A].toLowerCase().includes("application/x-www-form-urlencoded")&&(e=!0);break}if(h&&(e||["GET","OPTIONS","DELETE","TRACE","CONNECT"].includes(n))){var g,m=[];for(g in h)m.push(encodeURIComponent(g)+"="+encodeURIComponent(h[g]));h=m.join("&")}if(a)for(var y in a)a[y]=""+a[y];let t={method:n,extraData:h||{},header:a,expectDataType:l&&"arraybuffer"===l?http.HttpDataType.ARRAY_BUFFER:http.HttpDataType.STRING,usingCache:d||!1},o=!1,r=setTimeout(()=>{var e;console.error("[AdvancedAPI] request error: Timeout was reached"),o=!0,p&&!this.abortFlag&&(this.result=e={errMsg:"Timeout was reached"},p(e)),f&&!this.abortFlag&&f(this.result),this.httpRequest&&(this.httpRequest.destroy(),this.httpRequest=void 0)},c||6e4);this.httpRequest.request("string"==typeof i?i:"",t).then(a=>{if(clearTimeout(r),console.debug("[AdvancedAPI] request url %s success",i),u&&!this.abortFlag){let e=a.result,t=!1,o=(s||{}).responseType;if(o&&"json"!==o)"[object ArrayBuffer]"===Object.prototype.toString.call(e)&&(e=arrayBufferToBase64(e),t=!0);else if("string"==typeof a.result)try{e=JSON.parse(e)}catch(e){}o={isArrayBuffer:!1,data:e,statusCode:a.responseCode,header:a.header,cookies:"string"==typeof a.cookies?a.cookies?[a.cookies]:[]:a.cookies,errMsg:"request:ok"},t&&(o.isArrayBuffer=!0),this.result=o,u(o)}}).catch(e=>{clearTimeout(r),o||(console.error("[AdvancedAPI] request error: "+JSON.stringify(e)),p&&!this.abortFlag&&(e={errMsg:errMsgMap.has(e.code)?errMsgMap.get(e.code):"Unknown Error"},this.result=e,p(e)))}).finally(()=>{o||(f&&!this.abortFlag&&f(this.result),this.httpRequest&&(this.httpRequest.destroy(),this.httpRequest=void 0))})}else console.error("[AdvancedAPI] request error: params illegal")}abort(){console.debug("[AdvancedAPI] request abort"),this.abortFlag=!0,this.httpRequest&&(this.httpRequest.destroy(),this.httpRequest=void 0,this.res={errMsg:"request:fail abort"},this.fail&&this.fail(this.res),this.complete)&&this.complete(this.res)}onHeadersReceived(t){var e=e=>{this.abortFlag||t({header:e})};t?this.headersCallback.has(t)||(this.headersCallback.set(t,e),this.httpRequest&&this.httpRequest.on("headersReceive",e)):console.error("[AdvancedAPI] Invalid, callback is null")}offHeadersReceived(e){e?this.headersCallback.has(e)?(this.httpRequest&&this.httpRequest.off("headersReceive",this.headersCallback.get(e)),this.headersCallback.delete(e)):console.debug("[AdvancedAPI] offHeadersReceived callback invalid"):(this.headersCallback.clear(),this.httpRequest&&this.httpRequest.off("headersReceive"))}}class UploadTask{constructor(e){var{url:t,files:o,filePath:a,name:r,header:s,formData:i}=e||{};let{success:n,fail:c,complete:l}=e||{},d=(e=a.startsWith("internal://cache/")?a:pathToCache(a),this.progressCallback=new Map,this.headersCallback=new Map,[]);o?o.forEach(function(e){var t,o;"string"==typeof e.uri&&(t=e.uri.substring(e.uri.lastIndexOf("/")+1),o=e.uri.substring(e.uri.lastIndexOf(".")+1),d.push({filename:t,name:e.name,uri:e.uri,type:o}))}):"string"==typeof e&&(a=e.substring(e.lastIndexOf("/")+1),o=e.substring(e.lastIndexOf(".")+1),d.push({filename:a,name:r,uri:e,type:o}));var h,u,p=[];for([h,u]of Object.entries(i||{}))p.push({name:h,value:"string"==typeof u?u:JSON.stringify(u)});a={url:t,header:s||{},method:"POST",files:d,data:p},this.successHandle=e=>{n&&n(e),l&&l(e)},this.failHandle=e=>{c&&c(e),l&&l(e)};try{console.debug("[AdvancedAPI] request upload"),request$1.uploadFile(globalThis.abilityContext,a).then(e=>{if(this.uploadTask=e,this.abortFlag&&(this.abortFlag=!1,this.uploadTask.delete(()=>{this.res={errMsg:"uploadFile:fail abort"},this.failHandle(this.res)})),this.progressFlag){this.progressFlag=!1;for(var t of this.progressCallback.values())this.uploadTask.on("progress",t)}if(this.headersFlag){this.headersFlag=!1;for(var o of this.headersCallback.values())this.uploadTask.on("headerReceive",o)}this.uploadTask.on("headerReceive",this.headersReceivedHandle.bind(this)),this.uploadTask.on("complete",()=>{var e;console.debug("[AdvancedAPI] upload success"),this.res={data:(null==(e=this.receivedData)?void 0:e.body)||{},header:(null==(e=this.receivedData)?void 0:e.headers)||{},cookies:[],statusCode:200,errMsg:"uploadFile:ok"},this.successHandle(this.res)}),this.uploadTask.on("fail",()=>{console.debug("[AdvancedAPI] upload fail"),this.res={errMsg:"uploadFile:fail"},this.failHandle(this.res)})}).catch(e=>{console.error("[AdvancedAPI] upload request error: "+e.message),this.res={errMsg:"uploadFile:fail "+e.message},this.failHandle(this.res)})}catch(e){console.error("[AdvancedAPI] upload request err.code : "+e.code+", err.message : "+e.message),this.res={errMsg:"uploaddFile:fail "+e.message},this.failHandle(this.res)}}abort(){this.res={errMsg:"uploadFile:fail abort"},this.uploadTask?this.uploadTask.delete(()=>{this.failHandle(this.res)}):this.abortFlag=!0}onProgressUpdate(o){function e(e,t){o({progress:Math.ceil(100*e/t),totalBytesSent:e,totalBytesExpectedToSend:t})}o?this.progressCallback.has(o)||(this.progressCallback.set(o,e),this.uploadTask?this.uploadTask.on("progress",e):this.progressFlag=!0):console.error("[AdvancedAPI] Invalid, callback is null")}offProgressUpdate(e){e?this.progressCallback.has(e)?(this.uploadTask&&this.uploadTask.off("progress",this.progressCallback.get(e)),this.progressCallback.delete(e)):console.debug("[AdvancedAPI] offProgressUpdate callback invalid"):(this.progressCallback.clear(),this.uploadTask&&this.uploadTask.off("progress"))}headersReceivedHandle(e){this.receivedData=e}onHeadersReceived(t){var e=e=>{this.abortFlag||t({header:e.headers||{}})};t?this.headersCallback.has(t)||(this.headersCallback.set(t,e),this.uploadTask?this.uploadTask.on("headerReceive",e):this.headersFlag=!0):console.error("[AdvancedAPI] Invalid, callback is null")}offHeadersReceived(e){e?this.headersCallback.has(e)?(this.uploadTask&&this.uploadTask.off("headerReceive",this.headersCallback.get(e)),this.headersCallback.delete(e)):console.debug("[AdvancedAPI] offHeadersReceived callback invalid"):(this.headersCallback.clear(),this.uploadTask&&(this.uploadTask.off("headerReceive"),this.uploadTask.on("headerReceive",this.headersReceivedHandle.bind(this))))}}class DownloadTask{constructor(e){let{url:t,header:o,filePath:a}=e||{},{success:r,fail:s,complete:i}=e||{},n=(this.progressCallback=new Map,"string"==typeof t&&(e=(new Date).getTime(),this.filename="Download_"+e+"_"+t.substring(t.lastIndexOf("/")+1).replace(/[^a-zA-Z0-9.]/,"").slice(-16)),a||"internal://cache/"+this.filename);e=switchInternalToHapSandBox(n),e={url:this.isEncodeUri(t)?t:encodeURI(t),header:o||{},filePath:e},this.successHandle=e=>{r&&r(e),i&&i(e)},this.failHandle=e=>{s&&s(e),i&&i(e)};try{console.debug("[AdvancedAPI] request download"),request$1.downloadFile(globalThis.abilityContext,e).then(e=>{if(this.downloadTask=e,this.abortFlag&&(this.abortFlag=!1,this.downloadTask.delete(()=>{console.debug("[AdvancedAPI] download fail"),this.res={errMsg:"downloadFile:fail abort"},this.failHandle(this.res)})),this.progressFlag){this.progressFlag=!1;for(var t of this.progressCallback.values())this.downloadTask.on("progress",t)}this.downloadTask.on("complete",()=>{console.debug("[AdvancedAPI] download success"),this.res={tempFilePath:n,statusCode:200,errMsg:"downloadFile:ok"},a&&Object.assign(this.res,{filePath:a}),this.downloadTask.getTaskInfo().then(e=>{console.debug("[AdvancedAPI] download info: %s",JSON.stringify(e)),e.downloadTotalBytes&&Object.assign(this.res,{dataLength:e.downloadTotalBytes})}).catch(e=>{console.error("[AdvancedAPI] download request get task info error: "+e.message)}).finally(()=>{this.successHandle(this.res)})}),this.downloadTask.on("fail",()=>{console.debug("[AdvancedAPI] download fail"),this.res={errMsg:"downloadFile:fail"},this.failHandle(this.res)})}).catch(e=>{console.error("[AdvancedAPI] download request error: "+e.message),this.res={errMsg:"downloadFile:fail "+e.message},this.failHandle(this.res)})}catch(e){console.error("[AdvancedAPI] download request err.code : "+e.code+", err.message : "+e.message),this.res={errMsg:"downloadFile:fail "+e.message},this.failHandle(this.res)}}abort(){this.downloadTask?this.downloadTask.delete(()=>{console.debug("[AdvancedAPI] download fail"),this.res={errMsg:"downloadFile:fail abort"},this.failHandle(this.res)}):this.abortFlag=!0}onProgressUpdate(o){function e(e,t){o({progress:Math.ceil(100*e/t),totalBytesWritten:e,totalBytesExpectedToWrite:t})}o?this.progressCallback.has(o)||(this.progressCallback.set(o,e),this.downloadTask?this.downloadTask.on("progress",e):this.progressFlag=!0):console.error("[AdvancedAPI] Invalid, callback is null")}offProgressUpdate(e){e?this.progressCallback.has(e)?this.downloadTask&&(this.downloadTask.off("progress",this.progressCallback.get(e)),this.progressCallback.delete(e)):console.debug("[AdvancedAPI] offProgressUpdate callback invalid"):(this.progressCallback.clear(),this.downloadTask&&this.downloadTask.off("progress"))}onHeadersReceived(e){console.debug("[AdvancedAPI] onHeadersReceived not support")}offHeadersReceived(e){console.debug("[AdvancedAPI] offHeadersReceived not support")}isEncodeUri(e){return!e||/^[a-zA-Z0-9-_.!~*'();/?:@&=+$,#]+$/.test(e)}}let SCAN_MODE={LIMITED:5,DURATION:0};class BluetoothBase{static getPermissions(){let t=["ohos.permission.ACCESS_BLUETOOTH"],o=abilityAccessCtrl.createAtManager();return new Promise(async e=>{0===(await o.requestPermissionsFromUser(context,t)).authResults[0]?e(!0):e(!1)})}static onStateChange(e){try{return access.on("stateChange",e)}catch(e){console.warn("[AdvancedAPI] on bondStateChange fail")}}static on(e){try{return connection.on("bluetoothDeviceFind",e)}catch(e){console.warn("[AdvancedAPI] on fail")}}static onBLE(e){try{ble.on("BLEDeviceFind",e)}catch(e){console.warn("[AdvancedAPI] BLE.on.BLEDeviceFind fail")}}static createGattClientDevice(e){try{return ble.createGattClientDevice(e)}catch(e){console.warn("[AdvancedAPI] createGattClientDevice fail")}}static enableBluetooth(){try{return access.enableBluetooth()}catch(e){console.warn("[AdvancedAPI] enableBluetooth fail")}}static disableBluetooth(){try{return access.disableBluetooth()}catch(e){console.warn("[AdvancedAPI] disableBluetooth fail")}}static bluetoothState(){try{return access.getState()}catch(e){console.error("[AdvancedAPI] getState fail, errCode: "+e.code+", errMessage: "+e.message)}}static startBluetoothDiscovery(){connection.setBluetoothScanMode(connection.ScanMode.SCAN_MODE_LIMITED_DISCOVERABLE,SCAN_MODE.DURATION);try{return connection.startBluetoothDiscovery()}catch(e){console.warn("[AdvancedAPI] startBluetoothDiscovery fail")}}static off(){try{return connection.off("bluetoothDeviceFind")}catch(e){console.warn("[AdvancedAPI] off fail")}}static getRemoteDeviceName(e){try{return connection.getRemoteDeviceName(e)}catch(e){console.warn("[AdvancedAPI] getRemoteDeviceName fail")}}static stopBluetoothDiscovery(){try{return connection.stopBluetoothDiscovery()}catch(e){console.warn("[AdvancedAPI] no need to stop")}}static startBLEScan(e){try{ble.startBLEScan(null,{interval:e,dutyMode:ble.ScanDuty.SCAN_MODE_LOW_POWER,matchMode:ble.MatchMode.MATCH_MODE_AGGRESSIVE})}catch(e){console.error("[QAFAPI] startBLEScan errCode:"+e.code+",errMessage:"+e.message)}}static stopBLEScan(){try{ble.stopBLEScan()}catch(e){console.error("[QAFAPI] stopBLEScan errCode:"+e.code+",errMessage:"+e.message)}}static offBLE(){try{ble.off("BLEDeviceFind")}catch(e){console.warn("[AdvancedAPI] BLE.off.BLEDeviceFind fail")}}static getProfile(e){try{return bluetoothManager.getProfileInstance(e).getConnectionDevices()}catch(e){console.warn("[AdvancedAPI] getProfileInstance fail")}}static getConnectedBLEDevices(){try{return ble.getConnectedBLEDevices()}catch(e){console.error("[AdvancedAPI]getConnectedBLEDevices errCode:"+e.code+",errMessage:"+e.message)}}}function jsMethod(s){return(e,t,o)=>{var a=s&&s.common?e.constructor._jsBaseMethods=e.constructor._jsBaseMethods||{}:e.constructor._jsMethods=e.constructor._jsMethods||{},e=void 0!==(s=void 0!==s?s:{}).alias?s.alias:t,r=void 0===s.callback||s.callback;a[e]={methodName:t,callback:r}}}class PromptBase{static showToast(o){return new Promise((e,t)=>{promptAction.showToast(o),e()})}static showDialog(o,a){return new Promise((e,t)=>{promptAction.showDialog(o,a)})}static showActionMenu(o,a){return new Promise((e,t)=>{promptAction.showActionMenu(o,a)})}static ohosShowDialog(e){return promptAction.showDialog(e)}}let BLESTATE={STATE_ON:2,STATE_OFF:0,INDEX:1,STATE_CONNECTED:2,STATE_DISCONNECTED:0},DEFAULT={OPEN:!1,OPEN_MSG:"快应用加载器想要开启蓝牙",CLOSE_MSG:"快应用加载器请求关闭蓝牙",ALLOW_BUTTON:"允许",REFUSE_BUTTON:"拒绝"},BluetoothBaseModule=(_dec=jsMethod({alias:"openAdapter",common:!1,callback:!0}),_dec2=jsMethod({alias:"closeAdapter",common:!1,callback:!0}),_dec3=jsMethod({alias:"getAdapterState",common:!1,callback:!0}),_dec4=jsMethod({alias:"startDevicesDiscovery",common:!1,callback:!0}),_dec5=jsMethod({alias:"stopDevicesDiscovery",common:!1,callback:!0}),_dec6=jsMethod({alias:"getDevices",common:!1,callback:!0}),_dec7=jsMethod({alias:"getConnectedDevices",common:!1,callback:!0}),_dec8=jsMethod({alias:"createBLEConnection",common:!1,callback:!0}),_dec9=jsMethod({alias:"closeBLEConnection",common:!1,callback:!0}),_dec10=jsMethod({alias:"getBLEDeviceServices",common:!1,callback:!0}),_dec11=jsMethod({alias:"getBLEDeviceCharacteristics",common:!1,callback:!0}),_dec12=jsMethod({alias:"readBLECharacteristicValue",common:!1,callback:!0}),_dec13=jsMethod({alias:"writeBLECharacteristicValue",common:!1,callback:!0}),_dec14=jsMethod({alias:"notifyBLECharacteristicValueChange",common:!1,callback:!0}),_applyDecoratedDescriptor((_class=class{constructor(){_defineProperty(this,"BLECharacteristicCallback",e=>{console.debug("[AdvancedAPI] characteristicChange triger valueChange:"+JSON.stringify(e));var t,{serviceUuid:o,characteristicUuid:a}=e,e=new Uint8Array(e.characteristicValue),r={deviceId:this.deviceIdBle,serviceId:o,characteristicId:a,value:e};for(t of this.BLECharacteristicListeners)t(r)}),this.onadapterstatechange,this.ondevicefound,this.allowDuplicatesKey=!1,this.interval=0,this.state={available:BluetoothBase.bluetoothState()===BLESTATE.STATE_ON,discovering:!1},this.deviceIdBle,this.scanResult=[],this.gattClient=null,this.isOnBle={mode:!1},this.stateBLE={},this.services=[],this.bleCharacteristic={},this.characteristicValue=null,this.isInit=!1,this.devicesFoundListeners=[],this.adapterStateChangeListeners=[],this.BLEConnectionStateListeners=[],this.BLECharacteristicListeners=[]}openAdapter(e){let{operateAdapter:a=DEFAULT.OPEN}=e||{},r=BluetoothBase.bluetoothState()===BLESTATE.STATE_ON;return new Promise((t,o)=>{r?t([["bluetooth is turned"]]):a?this.promptTemp(DEFAULT.OPEN_MSG).then(e=>{e.index===BLESTATE.INDEX?(BluetoothBase.enableBluetooth()&&t([[BLHErrorCode.OK]]),this.state.available=!0):o([["user reject",BLHErrorCode.SYSTEM_ERROR]])}):o([["not available",BLHErrorCode.NOT_AVAILABLE]])})}closeAdapter(e){let{operateAdapter:o=DEFAULT.OPEN}=e||{},a=BluetoothBase.bluetoothState()===BLESTATE.STATE_OFF;return new Promise((t,e)=>{a?e([["bluetooth is not turned",BLHErrorCode.NOT_INIT]]):o?this.promptTemp(DEFAULT.CLOSE_MSG).then(e=>{if(e.index===BLESTATE.INDEX){BluetoothBase.disableBluetooth()&&t([[BLHErrorCode.OK]]),this.state.available=!1;try{BluetoothBase.offBLE()}catch(e){console.error("[QAFAPI] OpenHarmony Error ondevicefound,error Message:"+e)}}}):t([["closeBluetoothAdapter success"]])})}getAdapterState(){let t=BluetoothBase.bluetoothState()===BLESTATE.STATE_ON;return new Promise(e=>{e({discovering:this.state.discovering,available:t})})}startDevicesDiscovery(i){let t=BluetoothBase.bluetoothState()===BLESTATE.STATE_ON;return new Promise((e,o)=>{if(t){if(i){var{services:a,allowDuplicatesKey:r,interval:s}=i;if(a&&!isArray(a)||r&&!isBoolean(r)||s&&!isNumber(s))return void o([["invalidParam",BLHErrorCode.SYSTEM_ERROR]]);let t=[];if(a){if(!a.every(e=>(t.push({serviceUuid:e}),isUuid(e.toLowerCase()))))return void o([["uuid invalid",BLHErrorCode.NO_DEVICE]]);this.isOnBle.mode=!0}else t=null;r&&(this.allowDuplicatesKey=r),s&&(this.interval=s)}BluetoothBase.startBLEScan(this.interval),BluetoothBase.startBluetoothDiscovery()?(this.state.discovering=!0,e("ok")):o([["[QAFAPI] openHarmony startBluetoothDiscovery fail",BLHErrorCode.CONNECTION_FAIL]])}else o([["bluetooth is not turned",BLHErrorCode.NOT_AVAILABLE]])})}stopDevicesDiscovery(){return new Promise((e,t)=>{var o;BluetoothBase.bluetoothState()?(BluetoothBase.stopBLEScan(),o=BluetoothBase.stopBluetoothDiscovery(),this.state.discovering=!1,o?(e("ok"),this.devicesFoundListeners=[],this.isOnBle.mode=!1,this.interval=0,this.allowDuplicatesKey=!1):e("ok")):t(["bluetooth is not turned",BLHErrorCode.NOT_AVAILABLE])})}getDevices(){let o=BluetoothBase.bluetoothState()===BLESTATE.STATE_ON;return new Promise((e,t)=>{o?e([[{devices:this.scanResult}]]):t([["bluetooth is not turned",BLHErrorCode.NOT_AVAILABLE]])})}saveDevice(e){!this.allowDuplicatesKey&&this.isRepeat(this.scanResult,e.deviceId)||this.scanResult.push(e)}onFoundEvent(e){let a=this.getTemp();if(e[0]&&e[0].deviceId){var{deviceId:t,rssi:o,data:r}=e[0];a.deviceId=t,a.RSSI=o,a.serviceData=r;try{let o=BluetoothBase.createGattClientDevice(t);o.connect(),o.getDeviceName((e,t)=>{a.name=t,a.localName=t;try{o.disconnect(),o.close()}catch(e){console.warn("[QAFAPI] close client fail: "+JSON.stringify(e))}this.saveDevice(a)})}catch(e){console.warn("[QAFAPI] close client fail: "+JSON.stringify(e))}}else a.deviceId=e[0],a.name=BluetoothBase.getRemoteDeviceName(a.deviceId),a.localName=a.name,console.debug("[QAFAPI] onFoundEvent:"+JSON.stringify(a)),this.saveDevice(a)}getConnectedDevices(a){return new Promise((e,t)=>{if(BluetoothBase.bluetoothState()===BLESTATE.STATE_ON)if(a&&a.services&&isArray(a.services)&&0!==a.services.length){console.debug("[QAFAPI] services : "+JSON.stringify(a.services));var o=a.services.every(e=>isUuid(e.toLowerCase()))||!1;if(a&&o){let o=[];try{o=BluetoothBase.getConnectedBLEDevices()}catch(e){console.error("[QAFAPI] errCode:"+e.code+",errMessage:"+e.message)}console.debug("[QAFAPI] BleDeviceIds = "+JSON.stringify(o));try{[1,4,6,7].forEach(e=>{e=BluetoothBase.getProfile(e),console.error("[QAFAPI] profiles"+JSON.stringify(e)),e&&(o=[...o,...e])})}catch(e){console.error("[QAFAPI] getProfile fail"+e)}if((o=o.reduce((e,t)=>e.includes(t)?e:[...e,t],[]))&&0!==o.length){let t=[];o.forEach(e=>{t.push({name:BluetoothBase.getRemoteDeviceName(e),deviceId:e})}),e([[{devices:t}]])}else t([["no device",BLHErrorCode.NO_DEVICE]])}else console.debug("[QAFAPI] invalidParam services "),t([["invalidParam",BLHErrorCode.SYSTEM_ERROR]])}else t([["invalidParam",BLHErrorCode.SYSTEM_ERROR]]);else t([["bluetooth is not turned",BLHErrorCode.NOT_AVAILABLE]])})}createBLEConnection(e){let{deviceId:a,timeout:r}=e||{};return new Promise((t,o)=>{if(BluetoothBase.bluetoothState()===BLESTATE.STATE_ON)if(r&&!isNumber(r))o([["invalidParam",BLHErrorCode.SYSTEM_ERROR]]);else if(a&&isString(a)){this.gattClient=BluetoothBase.createGattClientDevice(a),this.gattClient.on("BLEConnectionStateChange",e=>{var t=2===e.state;this.stateBLE[e.deviceId]!==t&&(this.stateBLE[e.deviceId]=t)});try{this.gattClient.on("BLECharacteristicChange",this.BLECharacteristicCallback),console.debug("[AdvancedAPI] BLECharacteristicChange Registration succeeded.")}catch(e){console.error("AdvancedAPI BLECharacteristicChange Registration fail "+e.message)}let e=this.gattClient.connect();r?setTimeout(()=>{e?(t("ok"),this.deviceIdBle=a):o([["connection timed out",BLHErrorCode.CONNECTION_FAIL]])},r):e?(t("ok"),this.deviceIdBle=a):o([["fail connection",BLHErrorCode.CONNECTION_FAIL]])}else o([["invalidParam",BLHErrorCode.SYSTEM_ERROR]]);else o([["bluetooth is not turned",BLHErrorCode.NOT_AVAILABLE]])})}closeBLEConnection(e){let o=(e||{}).deviceId;return new Promise((e,t)=>{if(o&&isString(o))try{this.gattClient.disconnect(),this.gattClient.close(),this.gattClient=null,this.stateBLE[o]=!1,e("ok")}catch(e){t([["Failed to disconnect the Bluetooth connection",BLHErrorCode.SYSTEM_ERROR]])}else t([["Deviceid must be written",BLHErrorCode.SYSTEM_ERROR]])})}getBLEDeviceServices(e){let o=(e||{}).deviceId;return new Promise((t,e)=>{if(o&&isString(o))if(isMac(o))if(BluetoothBase.bluetoothState()===BLESTATE.STATE_ON){console.debug("[QAFAPI] getServices deviceId:"+o+" this.deviceIdBLE = "+this.deviceIdBle);let e;this.gattClient&&o===this.deviceIdBle?(console.debug("[QAFAPI] getServices deviceId:"+o),e=this.gattClient):((e=BluetoothBase.createGattClientDevice(o)).connect(),this.gattClient=e,this.deviceIdBle=o),e.getServices().then(e=>{let o=[];e.forEach(e=>{console.debug("[QAFAPI] getServices services = "+JSON.stringify(e));var{serviceUuid:e,isPrimary:t}=e,e={uuid:e,isPrimary:t};o.push(e)}),this.services=e,t([[{services:o}]])}).catch(e=>{console.error("[QAFAPI] getServices fail:"+JSON.stringify(e)),t([[{services:[]}]])})}else e([["bluetooth is not turned",BLHErrorCode.NOT_AVAILABLE]]);else e([["deviceId is not MAC",BLHErrorCode.SYSTEM_ERROR]]);else e([["invalidParam",BLHErrorCode.SYSTEM_ERROR]])})}getBLEDeviceCharacteristics(e){return new Promise((r,s)=>{if(e){let{deviceId:t,serviceId:a}=e;if(console.info("[QAFAPI] getBLEDeviceCharacteristics deviceId:"+t+" serviceId = "+a),t&&isString(t)&&a&&isString(a)){console.info("[QAFAPI] getBLEDeviceCharacteristics deviceId:"+t+" this.deviceIdBLE = "+this.deviceIdBle);let e;this.gattClient&&t===this.deviceIdBle?(console.info("[QAFAPI] getBLEDeviceCharacteristics deviceId:"+t),e=this.gattClient):((e=BluetoothBase.createGattClientDevice(t)).connect(),this.gattClient=e,this.deviceIdBle=t),e.getServices().then(e=>{let o;if(this.services.forEach(e=>{console.info("[QAFAPI] serviceId = "+JSON.stringify(e)),e.serviceUuid===a&&(o=e)}),o){let t=[];(this.bleDescriptor=o).characteristics.forEach(e=>{console.info("[QAFAPI] Servicesfound item = "+JSON.stringify(e)),t.push({uuid:e.characteristicUuid,properties:e.properties})}),r([[{characteristics:t}]])}else s([["Service not found",BLHErrorCode.NO_SERVICE]])}).catch(e=>{console.error("[QAFAPI] OpenHarmony Error getServices value,error Message:"+e),s([["property not support",BLHErrorCode.PROPERTY_NOT_SUPPORT]])})}else s([["invalidParam",BLHErrorCode.SYSTEM_ERROR]])}else s([["invalidParam",BLHErrorCode.SYSTEM_ERROR]])})}readBLECharacteristicValue(e){return new Promise((i,n)=>{if(e){let{deviceId:a,serviceId:r,characteristicId:s}=e;isString(a)&&isString(r)&&isString(s)&&a&&r&&isUuid(r.toLowerCase())&&s&&isUuid(s.toLowerCase())?isMac(a.toLowerCase())?this.queryBLECharacteristic(a,r).then(e=>{var t=[],e={serviceUuid:r.toLowerCase(),characteristicUuid:s.toLowerCase(),descriptorUuid:e.descriptorUuid,descriptorValue:e.descriptorValue},e=(t.push(e),{serviceUuid:r.toLowerCase(),characteristicUuid:s.toLowerCase(),characteristicValue:this.characteristicValue,descriptors:t}),t=(console.debug("[QAFAPI] characteristicIn = "+JSON.stringify(e)),null);let o;if(this.gattClient&&this.deviceIdBle===a)try{o=this.gattClient.readCharacteristicValue(e)}catch(e){n([[e.message,ErrorCode$1.PARAMETER_ERROR]]),console.error("[QAFAPI]readBLECharacteristicValue errCode:"+e.code+",errMessage:"+e.message)}else try{t=BluetoothBase.createGattClientDevice(a),o=t.readCharacteristicValue(e)}catch(e){n([[e.message,ErrorCode$1.PARAMETER_ERROR]]),console.error("[QAFAPI]readBLECharacteristicValue errCode:"+e.code+",errMessage:"+e.message)}o?o.then(e=>{i([e])}).catch(e=>{console.error("[AdvancedAPI] Failed to read characteristic value"+e.message),n([["property not support",BLHErrorCode.PROPERTY_NOT_SUPPORT]])}):n([["property not support",BLHErrorCode.PROPERTY_NOT_SUPPORT]])}).catch(e=>{n([["Bluetooth not available",BLHErrorCode.SYSTEM_ERROR]])}):n([["deviceId is not MAC",BLHErrorCode.SYSTEM_ERROR]]):n([["invalidParam",BLHErrorCode.SYSTEM_ERROR]])}else n([["invalidParam",BLHErrorCode.SYSTEM_ERROR]])})}writeBLECharacteristicValue(e){return new Promise((n,c)=>{if(e){let{deviceId:a,serviceId:r,characteristicId:s,value:i}=e;isString(a)&&isString(r)&&isString(s)&&isArrayBuffer(i)&&isMac(a)&&a&&r&&isUuid(r.toLowerCase())&&s&&isUuid(s.toLowerCase())&&isLower(s.toLowerCase())&&i?this.queryBLECharacteristic(a,r).then(e=>{var t=[],e={serviceUuid:r.toLowerCase(),characteristicUuid:s.toLowerCase(),descriptorUuid:e.descriptorUuid,descriptorValue:e.descriptorValue},e=(t.push(e),{serviceUuid:r.toLowerCase(),characteristicUuid:s.toLowerCase(),characteristicValue:i,descriptors:t}),t=(console.debug("[QAFAPI] characteristicIn = "+JSON.stringify(e)),null);let o;if(this.gattClient&&this.deviceIdBle===a)try{o=this.gattClient.writeCharacteristicValue(e)}catch(e){c([[e.message,ErrorCode$1.PARAMETER_ERROR]]),console.error("[QAFAPI]writeCharacteristicValue errCode:"+e.code+",errMessage:"+e.message)}else try{t=BluetoothBase.createGattClientDevice(a),o=t.writeCharacteristicValue(e)}catch(e){c([[e.message,ErrorCode$1.PARAMETER_ERROR]]),console.error("[QAFAPI]readBLECharacteristicValue errCode:"+e.code+",errMessage:"+e.message)}o?n("ok"):c([["property not support",BLHErrorCode.PROPERTY_NOT_SUPPORT]])}).catch(e=>{c([["Bluetooth not available",BLHErrorCode.SYSTEM_ERROR]])}):c([["invalidParam",BLHErrorCode.SYSTEM_ERROR]])}else c([["invalidParam",BLHErrorCode.SYSTEM_ERROR]])})}queryBLECharacteristic(t,r){return new Promise((o,a)=>{if(this.descriptors&&t.toLowerCase()===this.deviceIdBle.toLowerCase())o(this.descriptors);else{let e;this.gattClient&&t.toLowerCase()===this.deviceIdBle.toLowerCase()?(console.info("[QAFAPI] queryBLECharacteristic deviceId:"+t),e=this.gattClient):((e=BluetoothBase.createGattClientDevice(t)).connect(),this.gattClient=e,this.deviceIdBle=t),e.getServices().then(e=>{let t;e.forEach(e=>{e.serviceUuid.toLowerCase()===r.toLowerCase()&&(t=e)}),t?t.characteristics.forEach(e=>{e.serviceUuid.toLowerCase()===r.toLowerCase()?(this.characteristicValue=e.characteristicValue,e.descriptors.forEach(e=>{e.serviceUuid.toLowerCase()===r.toLowerCase()?(this.descriptors=e,console.info("[QAFAPI] Servicesfound descriptor = "+JSON.stringify(e)),o(this.descriptors)):a([["characteristics not found",BLHErrorCode.NO_SERVICE]])})):(console.error("[AdvancedAPI] characteristics not found"),a([["characteristics not found",BLHErrorCode.NO_SERVICE]]))}):a([["Service not found",BLHErrorCode.NO_SERVICE]])}).catch(e=>{console.error("[AdvancedAPI] getServices fail:"+e.message),a([["Service not found",BLHErrorCode.NO_SERVICE]])})}})}notifyBLECharacteristicValueChange(e){return new Promise((n,c)=>{if(e){let{deviceId:a,serviceId:r,characteristicId:s,state:i}=e;a&&isString(a)&&r&&isString(r)&&isUuid(r.toLowerCase())&&s&&isString(s)&&isUuid(s.toLowerCase())&&i&&isBoolean(i)?isMac(a.toLowerCase())?this.queryBLECharacteristic(a,r).then(e=>{console.debug("[QAFAPI] desc = "+JSON.stringify(e));var t=[],e={serviceUuid:r.toLowerCase(),characteristicUuid:s.toLowerCase(),descriptorUuid:e.descriptorUuid,descriptorValue:e.descriptorValue},e=(t.push(e),{serviceUuid:r.toLowerCase(),characteristicUuid:s.toLowerCase(),characteristicValue:this.characteristicValue,descriptors:t}),t=(console.debug("[QAFAPI] BLECharacteristic = "+JSON.stringify(e)),null);let o;if(this.gattClient&&this.deviceIdBle===a)try{o=this.gattClient.setNotifyCharacteristicChanged(e,i)}catch(e){return c([[e.message,ErrorCode$1.PARAMETER_ERROR]]),void console.error("[QAFAPI]setNotifyCharacteristicChanged errCode:"+e.code+",errMessage:"+e.message)}else try{t=BluetoothBase.createGattClientDevice(a),o=t.setNotifyCharacteristicChanged(e,i)}catch(e){return c([[e.message,ErrorCode$1.PARAMETER_ERROR]]),void console.error("[QAFAPI]setNotifyCharacteristicChanged errCode:"+e.code+",errMessage:"+e.message)}o?(console.debug("[QAFAPI] notify success"),n("ok")):c([["property not support",BLHErrorCode.PROPERTY_NOT_SUPPORT]])}):c([["deviceId is not MAC",BLHErrorCode.SYSTEM_ERROR]]):c([["invalidParam",BLHErrorCode.SYSTEM_ERROR]])}else c([["invalidParam",BLHErrorCode.SYSTEM_ERROR]])})}getBLEDeviceRSSI(a){return new Promise((t,o)=>{if(this.gattClient&&this.deviceIdBle===a)this.gattClient.getRssiValue().then(e=>{t(e)}).catch(e=>{o(e.message)});else try{var e=BluetoothBase.createGattClientDevice(a);e.connect(),this.gattClient=e,this.deviceIdBle=a,e.getRssiValue().then(e=>{t(e)}).catch(e=>{o(e.message)})}catch(e){o(e.message)}})}getTemp(){return{RSSI:"",localName:"",advertisData:"",advertisServiceUUIDs:"",name:"",serviceData:"",deviceId:""}}isRepeat(e,t){return e.some(e=>e.deviceId===t)}promptTemp(e){return PromptBase.ohosShowDialog({message:e,buttons:[{text:DEFAULT.REFUSE_BUTTON,color:"#1358e7"},{text:DEFAULT.ALLOW_BUTTON,color:"#1358e7"}]})}}).prototype,"openAdapter",[_dec],Object.getOwnPropertyDescriptor(_class.prototype,"openAdapter"),_class.prototype),_applyDecoratedDescriptor(_class.prototype,"closeAdapter",[_dec2],Object.getOwnPropertyDescriptor(_class.prototype,"closeAdapter"),_class.prototype),_applyDecoratedDescriptor(_class.prototype,"getAdapterState",[_dec3],Object.getOwnPropertyDescriptor(_class.prototype,"getAdapterState"),_class.prototype),_applyDecoratedDescriptor(_class.prototype,"startDevicesDiscovery",[_dec4],Object.getOwnPropertyDescriptor(_class.prototype,"startDevicesDiscovery"),_class.prototype),_applyDecoratedDescriptor(_class.prototype,"stopDevicesDiscovery",[_dec5],Object.getOwnPropertyDescriptor(_class.prototype,"stopDevicesDiscovery"),_class.prototype),_applyDecoratedDescriptor(_class.prototype,"getDevices",[_dec6],Object.getOwnPropertyDescriptor(_class.prototype,"getDevices"),_class.prototype),_applyDecoratedDescriptor(_class.prototype,"getConnectedDevices",[_dec7],Object.getOwnPropertyDescriptor(_class.prototype,"getConnectedDevices"),_class.prototype),_applyDecoratedDescriptor(_class.prototype,"createBLEConnection",[_dec8],Object.getOwnPropertyDescriptor(_class.prototype,"createBLEConnection"),_class.prototype),_applyDecoratedDescriptor(_class.prototype,"closeBLEConnection",[_dec9],Object.getOwnPropertyDescriptor(_class.prototype,"closeBLEConnection"),_class.prototype),_applyDecoratedDescriptor(_class.prototype,"getBLEDeviceServices",[_dec10],Object.getOwnPropertyDescriptor(_class.prototype,"getBLEDeviceServices"),_class.prototype),_applyDecoratedDescriptor(_class.prototype,"getBLEDeviceCharacteristics",[_dec11],Object.getOwnPropertyDescriptor(_class.prototype,"getBLEDeviceCharacteristics"),_class.prototype),_applyDecoratedDescriptor(_class.prototype,"readBLECharacteristicValue",[_dec12],Object.getOwnPropertyDescriptor(_class.prototype,"readBLECharacteristicValue"),_class.prototype),_applyDecoratedDescriptor(_class.prototype,"writeBLECharacteristicValue",[_dec13],Object.getOwnPropertyDescriptor(_class.prototype,"writeBLECharacteristicValue"),_class.prototype),_applyDecoratedDescriptor(_class.prototype,"notifyBLECharacteristicValueChange",[_dec14],Object.getOwnPropertyDescriptor(_class.prototype,"notifyBLECharacteristicValueChange"),_class.prototype),_class);class ASBluetooth extends BluetoothBaseModule{constructor(){super(),this.deviceFoundCallback=void 0,this.adapterStateCallback=void 0,this.BLEConnectionStateCallback=void 0,this.initBluetoothDeviceFound(),this.initBluetoothAdapterStateChange(),this.initBLEConnectionStateChange()}openBluetoothAdapter(){return new Promise(async(e,t)=>{if(!await BluetoothBase.getPermissions())return t(["permission fail",ErrorCode.USER_REJECT]);BluetoothBase.bluetoothState()===BLESTATE.STATE_ON?(this.isInit=!0,e("ok")):t([["not available",BLHErrorCode.NOT_AVAILABLE]])})}closeBluetoothAdapter(){let o=BluetoothBase.bluetoothState()===BLESTATE.STATE_OFF;return new Promise((e,t)=>{if(o)t([["bluetooth is not turned",BLHErrorCode.NOT_AVAILABLE]]);else{if(this.isInit=!1,BluetoothBase.stopBluetoothDiscovery(),this.state.discovering=!1,this.deviceIdBle="",this.scanResult=[],this.gattClient)try{this.gattClient.disconnect(),this.gattClient.close(),this.gattClient=null}catch(e){}this.isOnBle={mode:!1},this.stateBLE={},this.services=[],this.bleCharacteristic={},this.characteristicValue=null,this.devicesFoundListeners=[],this.adapterStateChangeListeners=[],this.BLEConnectionStateListeners=[],this.BLECharacteristicListeners=[],e("ok")}})}startBluetoothDevicesDiscovery(e){return this.isInit?this.startDevicesDiscovery(e):new Promise((e,t)=>{console.warn("[AdvancedAPI] bluetooth is no init"),t([["not init",BLHErrorCode.NOT_INIT]])})}stopBluetoothDevicesDiscovery(e){return this.isInit?this.stopDevicesDiscovery(e):new Promise((e,t)=>{console.warn("[AdvancedAPI] bluetooth is no init"),t([["not init",BLHErrorCode.NOT_INIT]])})}initBluetoothDeviceFound(){this.deviceFoundCallback=e=>{this.onFoundEvent(e);for(let e of this.devicesFoundListeners)setTimeout(()=>{e([this.scanResult])},this.interval)};try{BluetoothBase.on(this.deviceFoundCallback),BluetoothBase.onBLE(this.deviceFoundCallback)}catch(e){console.error("[AdvancedAPI] openHarmony ondevicefound fail "+e)}}onBluetoothDeviceFound(e){this.devicesFoundListeners.push(e)}offBluetoothDeviceFound(e){void 0===e?this.devicesFoundListeners.splice(0):"function"!=typeof e?console.error("[AdvancedAPI] offBluetoothAdapterStateChange, param is invalid:"+typeof e):-1<(e=this.devicesFoundListeners.indexOf(e))&&this.devicesFoundListeners.splice(e,1)}initBluetoothAdapterStateChange(){this.adapterStateCallback=e=>{var t=this.state.available;if(2===e?this.state.available=!0:0===e&&(this.state.available=!1),t!==this.state.available)for(var o of this.adapterStateChangeListeners)o(t)};try{BluetoothBase.onStateChange(e=>{this.adapterStateCallback(e)})}catch(e){console.error("[AdvancedAPI] onBluetoothAdapterStateChange errCode:"+e.code+",errMessage:"+e.message)}}onBluetoothAdapterStateChange(e){this.adapterStateChangeListeners.push(e)}offBluetoothAdapterStateChange(e){void 0===e?this.devicesFoundListeners.splice(0):"function"!=typeof e?console.error("[AdvancedAPI] offBluetoothAdapterStateChange, param is invalid:"):-1<(e=this.adapterStateChangeListeners.indexOf(e))&&this.adapterStateChangeListeners.splice(e,1)}getConnectedBluetoothDevices(e){return this.isInit?this.getConnectedDevices(e):new Promise((e,t)=>{console.warn("[AdvancedAPI] bluetooth is no init"),t([["not init",BLHErrorCode.NOT_INIT]])})}getBluetoothDevices(){return this.isInit?this.getDevices():new Promise((e,t)=>{console.warn("[AdvancedAPI] bluetooth is no init"),t([["not init",BLHErrorCode.NOT_INIT]])})}getBluetoothAdapterState(){return this.isInit?this.getAdapterState():new Promise((e,t)=>{console.warn("[AdvancedAPI] bluetooth is no init"),t([["not init",BLHErrorCode.NOT_INIT]])})}asSetBLEMTU(a){return new Promise((t,o)=>{if(a&&a.deviceId&&a.mtu)if(isString(a.deviceId)&&isNumber(a.mtu))try{console.debug("[AdvancedAPI] asSetBLEMTU deviceId:"+a.deviceId+" this.deviceIdBLE = "+this.deviceIdBle);let e;this.gattClient&&a.deviceId.toLowerCase()===this.deviceIdBle.toLowerCase()?(console.debug("[AdvancedAPI] asSetBLEMTU deviceId:"+a.deviceId),e=this.gattClient):((e=BluetoothBase.createGattClientDevice(a.deviceId)).connect(),this.gattClient=e,this.deviceIdBle=a.deviceId),this.gattClient.setBLEMtuSize(a.mtu),t("ok")}catch(e){console.error("[AdvancedAPI] setBLEMtuSize fail, errCode:"+e.code+",errMessage:"+e.message),o([[e.message,BLHErrorCode.SYSTEM_ERROR]])}else console.error("[AdvancedAPI] setBLEMTU fail, params error"),o([["param error",BLHErrorCode.SYSTEM_ERROR]]);else console.error("[AdvancedAPI] setBLEMTU fail, params error"),o([["param error",BLHErrorCode.SYSTEM_ERROR]])})}asWriteBLECharacteristicValue(e){return this.writeBLECharacteristicValue(e)}asReadBLECharacteristicValue(e){return this.readBLECharacteristicValue(e)}initBLEConnectionStateChange(){this.BLEConnectionStateCallback=t=>{this.BLEConnectionStateListeners.forEach(e=>{e(t)})},this.stateBLE=new Proxy({},{get:(e,t)=>e[t],set:(e,t,o)=>(e={deviceId:t,connected:e[t]=o},console.debug("AdvancedAPI bleConnectionStateChange"),this.BLEConnectionStateCallback(e),!0)})}asOnBLEConnectionStateChange(e){this.BLEConnectionStateListeners.push(e)}asOffBLEConnectionStateChange(e){void 0===e?this.BLEConnectionStateListeners.splice(0):"function"!=typeof e?console.error("[AdvancedAPI] offBLEConnectionStateChange, param is invalid:"):-1<(e=this.BLEConnectionStateListeners.indexOf(e))&&this.BLEConnectionStateListeners.splice(e,1)}asOnBLECharacteristicValueChange(e){this.BLECharacteristicListeners.push(e)}asOffBLECharacteristicValueChange(e){void 0===e?this.BLECharacteristicListeners.splice(0):"function"!=typeof e?console.error("[AdvancedAPI] offBLECharacteristicValueChange, param is invalid:"):-1<(e=this.BLECharacteristicListeners.indexOf(e))&&this.BLECharacteristicListeners.splice(e,1)}asNotifyBLECharacteristicValueChange(e){return console.debug("[AdvancedAPI] params = "+JSON.stringify(e)),this.notifyBLECharacteristicValueChange(e)}asGetBLEDeviceServices(e){return this.getBLEDeviceServices(e)}asGetBLEDeviceRSSI(e){return new Promise((t,o)=>{e&&e.deviceId&&"string"==typeof e.deviceId?this.getBLEDeviceRSSI(e.deviceId).then(e=>{t({rssi:e})}).catch(e=>{o([[e,BLHErrorCode.SYSTEM_ERROR]])}):o([["invalidParams",BLHErrorCode.SYSTEM_ERROR]])})}asGetBLEDeviceCharacteristics(e){return this.getBLEDeviceCharacteristics(e)}asCreateBLEConnection(e){return e&&console.info("[AdvancedAPI] asCreateBLEConnection params = "+JSON.stringify(e)),this.createBLEConnection(e)}asCloseBLEConnection(e){return this.closeBLEConnection(e)}}class ASRouter{navigateTo(r){return new Promise((e,t)=>{var o,a;"string"!=typeof r.url?t(["param url",ErrorCode$1.PARAMETER_ERROR]):({url:o,urlParams:a}=getUrlParams(r.url),console.debug("[AdvancedAPI] navigateTo urlParams = %s",JSON.stringify(a)),router.pushUrl({url:o,params:a}).then(()=>{e()}).catch(e=>{console.error(`[AdvancedAPI] pushUrl failed, code is ${e.code}, message is `+e.message),t([e.message,e.code])}))})}redirectTo(r){return new Promise((e,t)=>{var o,a;"string"!=typeof r.url?t(["param url",ErrorCode$1.PARAMETER_ERROR]):({url:o,urlParams:a}=getUrlParams(r.url),console.debug("[AdvancedAPI] redirectTo urlParams = "+JSON.stringify(a)),router.replaceUrl({url:o,params:a}).then(()=>{e()}).catch(e=>{console.error(`[AdvancedAPI] replaceUrl failed, code is ${e.code}, message is `+e.message),t([e.message,e.code])}))})}switchTab(e){return new Promise(async(e,t)=>{t("[AdvancedAPI] switchTab do not support")})}navigateBack(r){return new Promise((e,t)=>{let{delta:o=1}=r;if("number"!=typeof(o=null===o?1:o))t(["parameter delta",ErrorCode$1.PARAMETER_ERROR]);else{var a=Number(router.getLength());o>a&&(o=a-1);try{for(let e=0;e{e=e.split("="),t[e[0]]=e[1]}),{url:e,urlParams:t}}class WifiBase{static isWifiActive(){return wifi.isWifiActive()}static scan(){return wifi.scan()}static ohoGetLinkedInfo(){return new Promise((o,a)=>{wifi.getLinkedInfo((e,t)=>{e?(console.log("[QAFAPI] get linked info error:"+e),a(e)):(console.log("[QAFAPI] get wifi linked info: "+JSON.stringify(t)),o(t))})})}static connectionChange(e){wifi.on("wifiConnectionChange",e)}static scanStateChange(e){wifi.on("wifiScanStateChange",e)}static getScanInfos(){return new Promise((t,o)=>{wifi.getScanInfos().then(e=>{t(e)}).catch(e=>{console.info("[QAFAPI] getScanInfos error "+JSON.stringify(e)),o(e)})})}}_defineProperty(WifiBase,"ConnState",{SCANNING:0,CONNECTING:1,AUTHENTICATING:2,OBTAINING_IPADDR:3,CONNECTED:4,DISCONNECTING:5,DISCONNECTED:6,UNKNOWN:7}),_defineProperty(WifiBase,"StateType",{OFF:0,ON:1}),_defineProperty(WifiBase,"ScanState",{SUCCESS:1,FAIL:0}),_dec$1=jsMethod({alias:"scan",common:!1}),_dec2$1=jsMethod({alias:"getConnectedWifi",common:!1}),_applyDecoratedDescriptor((_class$1=class{constructor(){this.SecureType={WPA:"wpa",WEP:"wep"}}isSecure(e=""){return!(!(e=e.toLowerCase()).includes(this.SecureType.WPA)&&!e.includes(this.SecureType.WEP))}getSignalStrength(e){return e+100}scan(){return new Promise((e,t)=>{WifiBase.isWifiActive()?WifiBase.scan()?e([["scan success"]]):t([["scan fail",WifiErrorCode.WIFI_NOT_TURNED_ON]]):t([["wifi not turned on",WifiErrorCode.WIFI_NOT_TURNED_ON]])})}getConnectedWifi(a){return new Promise((s,o)=>{WifiBase.isWifiActive()?WifiBase.ohoGetLinkedInfo().then(async e=>{if(e.connState===WifiBase.ConnState.DISCONNECTED)o([["wifi is not connected",ErrorCode$1.COMMON_ERROR]]);else if(a){var t={SSID:e.ssid};s([[t]])}else{let t={BSSID:e.bssid,SSID:e.ssid,frequency:e.frequency,signalStrength:this.getSignalStrength(e.rssi),secure:!1},o,a=await WifiBase.getScanInfos(),r=a.length;for(let e=0;e{wifi.isWifiActive()||wifi.enableWifi()?(console.debug("[AdvancedAPI] enableWifi success"),e()):(console.debug("[AdvancedAPI] enableWifi fail"),t(["wifi not turned on",WifiErrorCode.WIFI_NOT_TURNED_ON]))})}stopWifi(){return new Promise((e,t)=>{!wifi.isWifiActive()||wifi.disableWifi()?(console.debug("[AdvancedAPI] stopWifi success"),e()):(console.debug("[AdvancedAPI] stopWifi fail"),t(["system not support",ErrorCode$1.COMMON_ERROR]))})}getConnectedWifi(a={}){return new Promise((t,o)=>{var{partialInfo:e=!1}=a;super.getConnectedWifi(e).then(([[e]])=>{t({wifi:e})},e=>{o(...e)})})}getWifiList(e){return new Promise((t,o)=>{super.scan().then(([e=[]]=[])=>{t(...e)},e=>{o(...e)})})}onGetWifiList(e){"function"!=typeof e?console.error("[AdvancedAPI] param is invalid."):this.wifiScanCallbacks.push(e)}offGetWifiList(e){0<=(e=this.wifiScanCallbacks.indexOf(e))?this.wifiScanCallbacks.splice(e,1):this.wifiScanCallbacks=[]}connectWifi(n){return new Promise(async(t,o)=>{let{SSID:a,BSSID:e="",password:r="",maunal:s=!1}=n;if(isString(a))if(isString(e))if(isString(r)){try{if((await this.getConnectedWifi()).wifi.SSID===a)return void t()}catch(e){console.debug("[AdvancedAPI] wifi is not connected.")}try{var i=await wifi.addDeviceConfig({ssid:a,bssid:e,preSharedKey:r,securityType:3,isHiddenSsid:!1});console.debug("[AdvancedAPI] addDeviceConfig success netId = %d",i),this._connectByNetId.push(e=>{(e.wifi.SSID===a?t:o)()}),s?console.error("[AdvancedAPI] 不支持跳转系统wlan页面"):wifi.connectToNetwork(i)}catch(e){console.error("[AdvancedAPI] connectWifi addDeviceConfig fail err = "+e),o(["system not support",ErrorCode$1.COMMON_ERROR])}}else console.error("[AdvancedAPI] connectWifi invalid password"),o(["wifi password error",WifiErrorCode.PASSWORD_ERROR]);else console.error("[AdvancedAPI] connectWifi invalid BSSID"),o(["wifi BSSID error",WifiErrorCode.PASSWORD_ERROR]);else console.error("[AdvancedAPI] connectWifi invalid SSID"),o(["wifi SSID error",WifiErrorCode.PASSWORD_ERROR])})}onWifiConnected(e){"function"!=typeof e?console.error("[AdvancedAPI] param is invalid."):this.connectCallbacks.push(e)}offWifiConnected(e){0<=(e=this.connectCallbacks.indexOf(e))?this.connectCallbacks.splice(e,1):this.connectCallbacks=[]}connectionChange(){WifiBase.connectionChange(e=>{e===WifiBase.StateType.ON?this.getConnectedWifi().then(({wifi:e})=>{e.state=WifiBase.StateType.ON,this.triggerConnectCallbacks({wifi:e}),this.triggerConnectWithPartialInfo({wifi:e}),this.triggerConnectById({wifi:e})},()=>{var e={BSSID:"",signalStrength:0,state:WifiBase.StateType.ON,secure:!1,SSID:""};this.triggerConnectCallbacks({wifi:e}),this.triggerConnectWithPartialInfo({wifi:e})}):e===WifiBase.StateType.OFF&&(e={BSSID:"",signalStrength:0,state:WifiBase.StateType.OFF,secure:!1,SSID:""},this.triggerConnectCallbacks({wifi:e}),this.triggerConnectWithPartialInfo({wifi:e}))})}scanChange(){WifiBase.scanStateChange(e=>{e===WifiBase.ScanState.SUCCESS&&WifiBase.getScanInfos().then(e=>{console.debug("[AdvancedAPI] onGetWifiList getScanInfos success"),e=e.map(e=>({BSSID:e.bssid,SSID:e.ssid,frequency:e.frequency,signalStrength:super.getSignalStrength(e.rssi),secure:super.isSecure(e.capabilities)})),this.triggerScanCallbacks({wifiList:e})})})}triggerConnectCallbacks(t){console.debug("[AdvancedAPI] triggerConnectCallbacks"),t.errMsg="onWifiConnected:ok",t.errCode=0,this.connectCallbacks.forEach(e=>{e(t)})}triggerConnectById(t){console.debug("[AdvancedAPI] triggerConnectById"),this._connectByNetId.forEach(e=>{e(t)}),this._connectByNetId=[]}triggerScanCallbacks(t){console.debug("[AdvancedAPI] wifiScanCallbacks"),this.wifiScanCallbacks.forEach(e=>{e(t)})}onWifiConnectedWithPartialInfo(e){"function"!=typeof e?console.error("[AdvancedAPI] param is invalid."):this.connectWithPartialInfo.push(e)}offWifiConnectedWithPartialInfo(e){0<=(e=this.connectWithPartialInfo.indexOf(e))?this.connectWithPartialInfo.splice(e,1):this.connectWithPartialInfo=[]}triggerConnectWithPartialInfo(e){console.debug("[AdvancedAPI] triggerConnectWithPartialInfo");let t={SSID:e.wifi.SSID};this.connectWithPartialInfo.forEach(e=>{e({wifi:t})})}}let AUTH_RESULT={PERMISSION_CHECK_FAIL:201,PARAM_ERROR:401,FAIL:12500001,OPEN_ERROR:12500002,USER_CANCEL:12500003,TIME_OUT:12500004,TYPE_UNSUPPORTED:12500005,TRUSTED_LEVEL_UNSUPPORTED:12500006,TASK_BUSY:12500007,AUTHENTICATOR_LOCKED:12500009,NOT_ENROLLED:12500010};function toUint8Arr(e){var t,o=[];for(t of e){var a=t.charCodeAt(0);a<128?o.push(a):a<2048?(o.push(192+(a>>6)),o.push(128+(63&a))):a<65536&&(o.push(224+(a>>12)),o.push(128+(a>>6&63)),o.push(128+(63&a)))}return Uint8Array.from(o)}class ASAuthentication{start(n){return new Promise((t,o)=>{if("facial"!==(n&&n.requestAuthModes||""))o({errCode:90003,errMsg:"The authentication type is not supported."});else{var e=toUint8Arr(n.challenge),a=n&&n.authContent||"",r=userIAM_userAuth.UserAuthType.FACE,s=userIAM_userAuth.AuthTrustLevel.ATL1;try{var i=userIAM_userAuth.getAuthInstance(e,r,s);i.on("result",{callback:e=>{console.debug("[AdvancedAPI] authV9 result "+e.result),console.debug("[AdvancedAPI] authV9 token "+e.token),console.debug("[AdvancedAPI] authV9 remainAttempts "+e.remainAttempts),console.debug("[AdvancedAPI] authV9 lockoutDuration "+e.lockoutDuration),e.result===AUTH_RESULT.PERMISSION_CHECK_FAIL?o({errCode:90002,errMsg:"Permission verification failed."}):e.result===AUTH_RESULT.PARAM_ERROR?o({errCode:90004,errMsg:"Incorrect parameters."}):e.result===AUTH_RESULT.FAIL?o({errCode:90009,errMsg:"Authentication failed."}):e.result===AUTH_RESULT.OPEN_ERROR?o({errCode:90009,errMsg:"General operation error."}):e.result===AUTH_RESULT.USER_CANCEL?o({errCode:90008,errMsg:"The operation is canceled."}):e.result===AUTH_RESULT.TIME_OUT?o({errCode:90007,errMsg:"The operation is time-out."}):e.result===AUTH_RESULT.TYPE_UNSUPPORTED?o({errCode:90003,errMsg:"The authentication type is not supported."}):e.result===AUTH_RESULT.TRUSTED_LEVEL_UNSUPPORTED?o({errCode:90003,errMsg:"The authentication trust level is not supported."}):e.result===AUTH_RESULT.TASK_BUSY?o({errCode:90010,errMsg:"The authentication task is busy."}):e.result===AUTH_RESULT.AUTHENTICATOR_LOCKED?o({errCode:90010,errMsg:"The authenticator is locked."}):e.result===AUTH_RESULT.NOT_ENROLLED?o({errCode:90011,errMsg:"The type of credential has not been enrolled."}):t({authMode:"facial",resultJSON:"",resultJSONSignature:"",errCode:0,errMsg:void 0})}}),i.on("tip",{callback:e=>{switch(e.tip){case userIAM_userAuth.FaceTips.FACE_AUTH_TIP_TOO_BRIGHT:prompt.showToast({message:"光线太强,获取的图像太亮。"});break;case userIAM_userAuth.FaceTips.FACE_AUTH_TIP_TOO_DARK:prompt.showToast({message:"光线太暗,获取的图像太暗。"});break;case userIAM_userAuth.FaceTips.FACE_AUTH_TIP_TOO_CLOSE:prompt.showToast({message:"人脸距离设备过近。"});break;case userIAM_userAuth.FaceTips.FACE_AUTH_TIP_TOO_FAR:prompt.showToast({message:"人脸距离设备过远。"});break;case userIAM_userAuth.FaceTips.FACE_AUTH_TIP_TOO_HIGH:prompt.showToast({message:"设备太高,仅获取到人脸上部。"});break;case userIAM_userAuth.FaceTips.FACE_AUTH_TIP_TOO_LOW:prompt.showToast({message:"设备太低,仅获取到人脸下部。"});break;case userIAM_userAuth.FaceTips.FACE_AUTH_TIP_TOO_RIGHT:prompt.showToast({message:"设备太靠右,仅获取到人脸右部。"});break;case userIAM_userAuth.FaceTips.FACE_AUTH_TIP_TOO_LEFT:prompt.showToast({message:"设备太靠左,仅获取到人脸左部。"});break;case userIAM_userAuth.FaceTips.FACE_AUTH_TIP_TOO_MUCH_MOTION:prompt.showToast({message:"在图像采集过程中,用户人脸移动太快。"});break;case userIAM_userAuth.FaceTips.FACE_AUTH_TIP_POOR_GAZE:prompt.showToast({message:"没有正视摄像头。"});break;case userIAM_userAuth.FaceTips.FACE_AUTH_TIP_NOT_DETECTED:prompt.showToast({message:"没有检测到人脸信息。"});break;default:console.debug("[AdvancedAPI] %s",JSON.stringify(e))}}}),a&&(console.debug("[AdvancedAPI] showToast authContent = %s",a),prompt.showToast({message:a})),i.start(),console.debug("[AdvancedAPI] authV9 start success")}catch(e){console.debug("[AdvancedAPI] authV9 start error = %s",e),o({errCode:90007,errMsg:"General operation fail."})}}})}getSupportedType(){return console.debug("[AdvancedAPI] start getSupportedType"),new Promise(e=>{e({supportMode:["facial"]})})}isEnrolled(a){return console.debug("[AdvancedAPI] start isEnrolled"),new Promise((e,t)=>{var o=a&&a.checkAuthMode||"";"fingerPrint"===o?e({isEnrolled:!1,errMsg:""}):"facial"===o&&e({isEnrolled:!1,errMsg:"The type of credential has not been enrolled."})})}}class OhosSensorBase{static ohosSubscribeAccelerometer(e){let{interval:t,callback:o}=e;sensor.on(sensor.SensorType.SENSOR_TYPE_ID_ACCELEROMETER,e=>{o(e)},{interval:t})}static ohosUnsubscribeAccelerometer(){sensor.off(sensor.SensorType.SENSOR_TYPE_ID_ACCELEROMETER)}static ohosSubscribeCompass(e){let t=e.callback;sensor.on(sensor.SensorType.SENSOR_TYPE_ID_ORIENTATION,e=>{t(e)})}static ohosUnsubscribeCompass(){sensor.off(sensor.SensorType.SENSOR_TYPE_ID_ORIENTATION)}static ohosSubscribeGyroscope(e){let{intervalValue:t,callback:o}=e;sensor.on(sensor.SensorId.GYROSCOPE,e=>{o(e)},{interval:t})}static ohosUnsubscribeGyroscope(){sensor.off(sensor.SensorId.GYROSCOPE)}}let intervalType=[{label:"game",value:2e7},{label:"ui",value:6e7},{label:"normal",value:2e8}];class ASAccelerometer{constructor(){this.callBackSet=new Set,this.defaultInterval="normal"}onAccelerometerChange(o){return new Promise((e,t)=>{"function"!=typeof o||this.callBackSet.has(o)?t("param is invalid.",ErrorCode$1.PARAMETER_ERROR):(this.callBackSet.add(o),t=intervalType.find(e=>e.label===this.defaultInterval).value,OhosSensorBase.ohosSubscribeAccelerometer({interval:t,callback:e=>{var t,o={x:e.x,y:e.y,z:e.z};for(t of this.callBackSet.keys())t(o)}}),e())})}offAccelerometerChange(o){return new Promise((e,t)=>{"function"!=typeof o?(this.callBackSet.clear(),OhosSensorBase.ohosUnsubscribeAccelerometer(),e()):this.callBackSet.has(o)?(this.callBackSet.delete(o),0===this.callBackSet.size&&OhosSensorBase.ohosUnsubscribeAccelerometer(),e()):t("param is invalid.",ErrorCode$1.COMMON_ERROR)})}startAccelerometer(r){return new Promise((e,t)=>{let o=intervalType.find(e=>e.label===this.defaultInterval).value;var a;r.interval&&"string"==typeof r.interval&&(a=intervalType.find(e=>e.label===r.interval))&&(o=a.value),OhosSensorBase.ohosSubscribeAccelerometer({interval:o,callback:e=>{var t,o={x:e.x,y:e.y,z:e.z};for(t of this.callBackSet.keys())t(o)}}),e()})}stopAccelerometer(){return new Promise((e,t)=>{OhosSensorBase.ohosUnsubscribeAccelerometer(),e()})}}class ASCompass{constructor(){this.callBackCompassSet=new Set}onCompassChange(o){return new Promise(async(e,t)=>{"function"!=typeof o||this.callBackCompassSet.has(o)?t("param is invalid.",ErrorCode$1.PARAMETER_ERROR):(this.callBackCompassSet.add(o),OhosSensorBase.ohosSubscribeCompass({callback:e=>{var t,o={direction:e.alpha,accuracy:e.alpha?3:0};for(t of this.callBackCompassSet.keys())t(o)}}),e())})}offCompassChange(o){return new Promise(async(e,t)=>{"function"==typeof o&&this.callBackCompassSet.has(o)?(this.callBackCompassSet.delete(o),0===this.callBackCompassSet.size&&OhosSensorBase.ohosUnsubscribeCompass(),e("success")):t("param is invalid.",ErrorCode$1.PARAMETER_ERROR)})}startCompass(e){return new Promise(async(e,t)=>{OhosSensorBase.ohosSubscribeCompass({callback:e=>{var t,o={direction:e.alpha,accuracy:e.alpha?3:0};for(t of this.callBackCompassSet.keys())t(o)}}),e("success")})}stopCompass(){return new Promise(async(e,t)=>{OhosSensorBase.ohosUnsubscribeCompass(),e("success")})}}let intervalType$1=[{label:"game",value:2e7},{label:"ui",value:6e7},{label:"normal",value:2e8}];class ASGyroscope{constructor(){this.callBackGyroscopeSet=new Set}onGyroscopeChange(o){return new Promise((e,t)=>{"function"!=typeof o||this.callBackGyroscopeSet.has(o)?t("param is invalid.",ErrorCode$1.PARAMETER_ERROR):(this.callBackGyroscopeSet.add(o),e())})}startGyroscope(r={}){return new Promise((e,t)=>{let o=intervalType$1.find(e=>"normal"===e.label).value;var a;r.interval&&"string"==typeof r.interval&&(a=intervalType$1.find(e=>e.label===r.interval))&&(o=a.value),OhosSensorBase.ohosSubscribeGyroscope({intervalValue:o,callback:e=>{var t,o={x:e.x,y:e.y,z:e.z};for(t of this.callBackGyroscopeSet.keys())t(o)}}),e()})}stopGyroscope(){return new Promise((e,t)=>{OhosSensorBase.ohosUnsubscribeGyroscope(),e()})}}class ASContact{addPhoneContact(D){return new Promise(async(t,o)=>{try{var{authResults:e,dialogShownResults:a}=await abilityAccessCtrl.createAtManager().requestPermissionsFromUser(context,["ohos.permission.WRITE_CONTACTS"]);if(0!==e[0])return void o(["request permission fail",ErrorCode$1.USER_REJECT,e[0],a[0]]);console.debug("[AdvancedAPI] request WRITE_CONTACTS permission success")}catch(e){return void o(["request permission fail",ErrorCode$1.USER_REJECT])}var{photoFilePath:e,nickName:a="",lastName:r="",middleName:s="",firstName:i="",remark:n,mobilePhoneNumber:c,weChatNumber:l,addressCountry:d="",addressState:h="",addressCity:u="",addressStreet:p="",addressPostalCode:f,organization:A,url:g,workPhoneNumber:m,workFaxNumber:y,hostNumber:S,email:v,title:C,workAddressCountry:P="",workAddressState:E="",workAddressCity:b="",workAddressStreet:I="",workAddressPostalCode:T,homeFaxNumber:R,homePhoneNumber:k,homeAddressCountry:_="",homeAddressState:B="",homeAddressCity:O="",homeAddressStreet:w="",homeAddressPostalCode:L}=D;l||console.error("[AdvancedAPI] weChatNumber do not support."),i?(l={name:{familyName:r,middleName:s,givenName:i,fullName:r+s+i},nickName:{nickName:a},emails:[{email:v,displayName:"邮箱"}],phoneNumbers:[{phoneNumber:k,labelId:contact.PhoneNumber.NUM_HOME},{phoneNumber:c,labelId:contact.PhoneNumber.NUM_MOBILE},{phoneNumber:R,labelId:contact.PhoneNumber.NUM_FAX_HOME},{phoneNumber:y,labelId:contact.PhoneNumber.NUM_FAX_WORK},{phoneNumber:m,labelId:contact.PhoneNumber.NUM_WORK},{phoneNumber:S,labelId:contact.PhoneNumber.NUM_COMPANY_MAIN}],portrait:{uri:e},postalAddresses:[{city:O,country:_,postcode:L,street:w,postalAddress:_+B+O+w,labelId:contact.PostalAddress.ADDR_HOME},{city:b,country:P,postcode:T,street:I,postalAddress:P+E+b+I,labelId:contact.PostalAddress.ADDR_WORK},{city:u,country:d,postcode:f,street:p,postalAddress:d+h+u+p,labelId:contact.PostalAddress.CUSTOM_LABEL}],websites:[{website:g}],note:{noteContent:n},organization:{name:A,title:C}},contact.addContact(l).then(e=>{console.debug("[AdvancedAPI] addContact callback: success contactId = "+e),t()}).catch(e=>{console.debug("[AdvancedAPI] addContact callback: err->"+JSON.stringify(e)),o([e.data,e.code])})):(console.error("[AdvancedAPI] firstName is required."),o(["fail Missing required parameter `firstName`",ErrorCode$1.PARAMETER_ERROR]))})}}class ASVibrator{vibrate(){return new Promise((t,o)=>{this.triggerVibrate({duration:200}).then(e=>{t(e)}).catch(e=>{o([e.data,e.code])})})}vibrateLong(){return new Promise((t,o)=>{this.triggerVibrate({duration:400}).then(e=>{t(e)}).catch(e=>{o([e.data,e.code])})})}vibrateShort(){return new Promise((t,o)=>{this.triggerVibrate({duration:15}).then(e=>{t(e)}).catch(e=>{o([e.data,e.code])})})}triggerVibrate(a){return new Promise((t,o)=>{var e={type:"time",duration:a.duration};vibrator.startVibration(e,{id:0,usage:"alarm"}).then(e=>{console.debug("[AdvancedAPI] startVibration success"),t(e)},e=>{console.error("[AdvancedAPI] startVibration fail err = "+JSON.stringify(e)),o(e)}).catch(e=>{console.error("[AdvancedAPI] startVibration fail err = "+JSON.stringify(e)),o(e)})})}}class ASCapture{constructor(){this.captureCallback=null}onUserCaptureScreen(t){if(t)try{window.getLastWindow(globalThis.abilityContext).then(e=>{this.windowClass=e,this.captureCallback&&(this.windowClass.off("screenshot"),this.captureCallback=null),this.captureCallback=t,console.info("[AdvancedAPI] Succeeded in obtaining the top window. Listen to screenshot event.");try{this.windowClass.on("screenshot",function(){t("ohos not support path")})}catch(e){console.error("[AdvancedAPI] Failed to register callback. Cause: "+JSON.stringify(e))}}).catch(e=>{console.error("[AdvancedAPI] Failed to obtain the top window. Cause: "+JSON.stringify(e))})}catch(e){console.error("[AdvancedAPI] Failed to obtain the top window. Cause: "+JSON.stringify(e))}else console.error("[AdvancedAPI] params illegal, empty callback")}offUserCaptureScreen(t){try{window.getLastWindow(globalThis.abilityContext).then(e=>{this.windowClass=e,console.info("[AdvancedAPI] Succeeded in obtaining the top window. Unsubscribe screenshot event.");try{!t||this.captureCallback&&this.captureCallback===t?(this.windowClass.off("screenshot"),this.captureCallback=null):console.info("[AdvancedAPI] Invalid callback.")}catch(e){console.error("[AdvancedAPI] Failed to unregister callback. Cause: "+JSON.stringify(e))}}).catch(e=>{console.error("[AdvancedAPI] Failed to obtain the top window. Cause: "+JSON.stringify(e))})}catch(e){console.error("[AdvancedAPI] Failed to obtain the top window. Cause: "+JSON.stringify(e))}}}class ASKeyboard{constructor(){this.changeCallback=new Map}hideKeyboard(){return new Promise((e,t)=>{try{inputMethod.getController().hideTextInput().then(()=>{console.debug("[AdvancedAPI] Succeeded in hiding softKeyboard."),e()}).catch(e=>{console.error("[AdvancedAPI] Failed to hideSoftKeyboard: "+JSON.stringify(e)),t()})}catch(e){console.error("[AdvancedAPI] Failed to get inputMethod Controller. Cause: "+JSON.stringify(e)),t()}})}onKeyboardHeightChange(o){if(o)try{window.getLastWindow(globalThis.abilityContext).then(e=>{this.windowClass=e;let t=DisplayBase.ohosGetDisplay().densityPixels;this.changeCallback.has(o)||this.changeCallback.set(o,function(e){o({height:Math.round(e/t)})}),console.info("[AdvancedAPI] Succeeded in obtaining the top window. Listen to keyboard height change");try{this.windowClass.on("keyboardHeightChange",this.changeCallback.get(o))}catch(e){console.error("[AdvancedAPI] Failed to enable the listener for keyboard height changes. Cause: "+JSON.stringify(e))}}).catch(e=>{console.error("[AdvancedAPI] Failed to obtain the top window. Cause: "+JSON.stringify(e))})}catch(e){console.error("[AdvancedAPI] Failed to obtain the top window. Cause: "+JSON.stringify(e))}else console.error("[AdvancedAPI] params illegal, empty callback")}offKeyboardHeightChange(t){try{window.getLastWindow(globalThis.abilityContext).then(e=>{this.windowClass=e,console.info("[AdvancedAPI] Succeeded in obtaining the top window. Unsubscribe keyboard change event.");try{t?this.changeCallback.has(t)?(this.windowClass.off("keyboardHeightChange",this.changeCallback.get(t)),this.changeCallback.delete(t)):console.info("[AdvancedAPI] Invalid callback."):(this.windowClass.off("keyboardHeightChange"),this.changeCallback.clear())}catch(e){console.error("[AdvancedAPI] Failed to unregister callback. Cause: "+JSON.stringify(e))}}).catch(e=>{console.error("[AdvancedAPI] Failed to obtain the top window. Cause: "+JSON.stringify(e))})}catch(e){console.error("[AdvancedAPI] Failed to obtain the top window. Cause: "+JSON.stringify(e))}}}class FileioBase{static ohosOpendirSync(e){return new OhosOpendir(e)}static ohosReadSync(e,t){return fs.readSync(e,t)}static ohosUnlinkSync(e){return fs.unlinkSync(e)}static ohosCopy(e,t,o=0){return fs.copyFile(e,t,o)}static ohosMkdirSync(e,t=0){return fs.mkdirSync(e)}static ohosReadTextSync(e,t){return fs.readTextSync(e,t)}static ohosStatSync(e){return fs.statSync(e)}static ohosOpenSync(e,t,o=0){return e&&"string"==typeof e&&e.startsWith("/data/storage/")&&(e=fileuri.getUriFromPath(e)),fs.openSync(e,t)}static ohosWriteSync(e,t,o={}){return fs.writeSync(e,t,o)}static ohosAccessSync(e,t=0){return fs.accessSync(e)}}class OhosOpendir{constructor(e){this.dir=fs.listFileSync(e)}ohosReadsync(){return this.dir}}class WantConstantBase{static getAction(e){return wantConstant.Action[e]}}let version="3.7.7",VERSION=version,_hasBuffer="function"==typeof Buffer,_TD="function"==typeof TextDecoder?new TextDecoder:void 0,_TE="function"==typeof TextEncoder?new TextEncoder:void 0,b64ch="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",b64chs=Array.prototype.slice.call(b64ch),b64tab=(e=>{let o={};return e.forEach((e,t)=>o[e]=t),o})(b64chs),b64re=/^(?:[A-Za-z\d+\/]{4})*?(?:[A-Za-z\d+\/]{2}(?:==)?|[A-Za-z\d+\/]{3}=?)?$/,_fromCC=String.fromCharCode.bind(String),_U8Afrom="function"==typeof Uint8Array.from?Uint8Array.from.bind(Uint8Array):e=>new Uint8Array(Array.prototype.slice.call(e,0)),_mkUriSafe=e=>e.replace(/=/g,"").replace(/[+\/]/g,e=>"+"==e?"-":"_"),_tidyB64=e=>e.replace(/[^A-Za-z0-9\+\/]/g,""),btoaPolyfill=t=>{let o,a,r,s,i="",e=t.length%3;for(let e=0;e>18&63]+b64chs[o>>12&63]+b64chs[o>>6&63]+b64chs[63&o]}return e?i.slice(0,e-3)+"===".substring(e):i},_btoa="function"==typeof btoa?e=>btoa(e):_hasBuffer?e=>Buffer.from(e,"binary").toString("base64"):btoaPolyfill,_fromUint8Array=_hasBuffer?e=>Buffer.from(e).toString("base64"):o=>{var a=[];for(let e=0,t=o.length;et?_mkUriSafe(_fromUint8Array(e)):_fromUint8Array(e),cb_utob=e=>{var t;return e.length<2?(t=e.charCodeAt(0))<128?e:t<2048?_fromCC(192|t>>>6)+_fromCC(128|63&t):_fromCC(224|t>>>12&15)+_fromCC(128|t>>>6&63)+_fromCC(128|63&t):(t=65536+1024*(e.charCodeAt(0)-55296)+(e.charCodeAt(1)-56320),_fromCC(240|t>>>18&7)+_fromCC(128|t>>>12&63)+_fromCC(128|t>>>6&63)+_fromCC(128|63&t))},re_utob=/[\uD800-\uDBFF][\uDC00-\uDFFFF]|[^\x00-\x7F]/g,utob=e=>e.replace(re_utob,cb_utob),_encode=_hasBuffer?e=>Buffer.from(e,"utf8").toString("base64"):_TE?e=>_fromUint8Array(_TE.encode(e)):e=>_btoa(utob(e)),encode=(e,t=!1)=>t?_mkUriSafe(_encode(e)):_encode(e),encodeURI$1=e=>encode(e,!0),re_btou=/[\xC0-\xDF][\x80-\xBF]|[\xE0-\xEF][\x80-\xBF]{2}|[\xF0-\xF7][\x80-\xBF]{3}/g,cb_btou=e=>{switch(e.length){case 4:var t=((7&e.charCodeAt(0))<<18|(63&e.charCodeAt(1))<<12|(63&e.charCodeAt(2))<<6|63&e.charCodeAt(3))-65536;return _fromCC(55296+(t>>>10))+_fromCC(56320+(1023&t));case 3:return _fromCC((15&e.charCodeAt(0))<<12|(63&e.charCodeAt(1))<<6|63&e.charCodeAt(2));default:return _fromCC((31&e.charCodeAt(0))<<6|63&e.charCodeAt(1))}},btou=e=>e.replace(re_btou,cb_btou),atobPolyfill=t=>{if(t=t.replace(/\s+/g,""),!b64re.test(t))throw new TypeError("malformed base64.");t+="==".slice(2-(3&t.length));let o,a="",r,s;for(let e=0;e>16&255):64===s?_fromCC(o>>16&255,o>>8&255):_fromCC(o>>16&255,o>>8&255,255&o);return a},_atob="function"==typeof atob?e=>atob(_tidyB64(e)):_hasBuffer?e=>Buffer.from(e,"base64").toString("binary"):atobPolyfill,_toUint8Array=_hasBuffer?e=>_U8Afrom(Buffer.from(e,"base64")):e=>_U8Afrom(_atob(e).split("").map(e=>e.charCodeAt(0))),toUint8Array=e=>_toUint8Array(_unURI(e)),_decode=_hasBuffer?e=>Buffer.from(e,"base64").toString("utf8"):_TD?e=>_TD.decode(_toUint8Array(e)):e=>btou(_atob(e)),_unURI=e=>_tidyB64(e.replace(/[-_]/g,e=>"-"==e?"+":"/")),decode=e=>_decode(_unURI(e)),isValid=e=>"string"==typeof e&&(e=e.replace(/\s+/g,"").replace(/={0,2}$/,""),!/[^\s0-9a-zA-Z\+/]/.test(e)||!/[^\s0-9a-zA-Z\-_]/.test(e)),_noEnum=e=>({value:e,enumerable:!1,writable:!0,configurable:!0}),extendString=function(){var e=(e,t)=>Object.defineProperty(String.prototype,e,_noEnum(t));e("fromBase64",function(){return decode(this)}),e("toBase64",function(e){return encode(this,e)}),e("toBase64URI",function(){return encode(this,!0)}),e("toBase64URL",function(){return encode(this,!0)}),e("toUint8Array",function(){return toUint8Array(this)})},extendUint8Array=function(){var e=(e,t)=>Object.defineProperty(Uint8Array.prototype,e,_noEnum(t));e("toBase64",function(e){return fromUint8Array(this,e)}),e("toBase64URI",function(){return fromUint8Array(this,!0)}),e("toBase64URL",function(){return fromUint8Array(this,!0)})},extendBuiltins=()=>{extendString(),extendUint8Array()},gBase64={version:version,VERSION:VERSION,atob:_atob,atobPolyfill:atobPolyfill,btoa:_btoa,btoaPolyfill:btoaPolyfill,fromBase64:decode,toBase64:encode,encode:encode,encodeURI:encodeURI$1,encodeURL:encodeURI$1,utob:utob,btou:btou,decode:decode,isValid:isValid,fromUint8Array:fromUint8Array,toUint8Array:toUint8Array,extendString:extendString,extendUint8Array:extendUint8Array,extendBuiltins:extendBuiltins};class ASImage{constructor(){_defineProperty(this,"getArrayBuffer",async(e,t,o,a,r)=>{var s,i,n;return void 0!==a||void 0!==r?(a=r||a||0,n=image.createImageSource(t),i=image.createImagePacker(),r=(s=await n.getImageInfo()).size.width/r,n=await n.createPixelMap({desiredSize:{width:a,height:s.size.height/r}}),await i.packing(n,{format:"image/jpeg",quality:e})):(a=image.createImageSource(t),s=image.createImagePacker(),r={format:"image/jpeg",quality:e},i=await a.getImageInfo(),n=await a.createPixelMap({desiredSize:{width:i.size.width,height:i.size.height}}),await s.packing(n,r))})}chooseImage(n){return n=n||{},new Promise(async(e,t)=>{var o=await MediaLibraryBase.getPermissions();if(-1===o.perNum)return t(["permission fail",ErrorCode$1.USER_REJECT,o.perNum,o.dialogShownResults]);if(n.count&&"number"!=typeof n.count)return t(['chooseImage:fail parameter `count`. Expected Number with value NaN, got String with value "'+n.count+'".',ErrorCode$1.PARAMETER_ERROR]);n.count<1&&(n.count=9);let a=[];if(n.sourceType&&1===n.sourceType.length&&n.sourceType.includes("camera")){if(o=await bundleManager.getBundleInfoForSelf(bundleManager.BundleFlag.GET_BUNDLE_INFO_DEFAULT),0!==(o=await context.startAbilityForResult({action:WantConstantBase.getAction("ACTION_IMAGE_CAPTURE"),parameters:{uri:"capture",callBundleName:o.name}})).resultCode)return t(["Failed to pull up camera app",ErrorCode$1.SERVICE_UNAVIALABLE]);if(a=[o.want.parameters.resourceUri],!o.want.parameters.resourceUri)return}else(o=new picker.PhotoSelectOptions).MIMEType=picker.PhotoViewMIMETypes.IMAGE_TYPE,o.maxSelectNumber=n.count,o=await(new picker.PhotoViewPicker).select(o),a=o.photoUris;if(!a)return t(["get uri fail",ErrorCode$1.SERVICE_UNAVIALABLE]);if("cancel"!==a){var r,s=[],i=[];for(let e=0;e{try{var o,a,r,s,i,n=c.src;return isFileUri(n)?(a={0:"up",90:"right",180:"down",270:"left"}[(o=await getFileAssetFromUri(n)).orientation],e({width:o.width,height:o.height,path:n,orientation:a,type:o.displayName.split(".").pop()})):isSandboxPath(n)?(r=image.createImageSource(switchInternalToHapSandBox(n)),s=n.split(".").pop(),e({width:(i=await r.getImageInfo()).size.width,height:i.size.height,path:c.src,orientation:"up",type:s})):t(["get uri fail",ErrorCode$1.SERVICE_UNAVIALABLE])}catch(e){return t(["get uri fail",ErrorCode$1.SERVICE_UNAVIALABLE])}})}saveImageToPhotosAlbum(v){return new Promise(async(o,e)=>{try{var t,a,r,s,i,n,c=v.filePath;if("string"!=typeof c)return e(["filePath format is not supported.",ErrorCode$1.PARAMETER_ERROR]);if(isFileUri(c))a=getFdFromUriOrSandBoxPath(t=c),r=fs.statSync(a).size,s=new ArrayBuffer(r),FileioBase.ohosReadSync(a,s),i=await getFileAssetFromUri(t),n="IMAGE_"+(new Date).getTime()+"_"+i.displayName,o({path:await saveMedia(photoAccessHelper.PhotoType.IMAGE,n,t,s)});else if(isSandboxPath(c)){let t=c;if(t.startsWith("internal://")&&(t=switchInternalToHapSandBox(c)),fs.accessSync(t)){var l=fs.openSync(t,fs.OpenMode.READ_ONLY);if(l){var d=l.fd,h=fs.statSync(t).size,u=new ArrayBuffer(h);FileioBase.ohosReadSync(d,u);let e="IMAGE_"+(new Date).getTime()+"_"+t.split("/").splice(-1,1).toString();e.includes(".")||(e+=".jpg"),t=fileuri.getUriFromPath(t),o({path:await saveMedia(photoAccessHelper.PhotoType.IMAGE,e,t,u)})}else e(["saveImageToPhotosAlbum fail, src not exist.",ErrorCode$1.PARAMETER_ERROR])}else e(["saveImageToPhotosAlbum fail, src not exist.",ErrorCode$1.PARAMETER_ERROR])}else{if(c.startsWith("data:image/")){var p=c.split(";");if(2===p.length&&p[1].startsWith("base64")){var f=p[0].replace("data:image/",""),A=gBase64.atob(c.split(",")[1]),g="IMAGE_"+(new Date).getTime()+"."+f,m=new ArrayBuffer(A.length),y=new Uint8Array(m);for(let e=0;e{let n=switchInternalToHapSandBox(p.src),c=0<=(n.split("/").pop()||"").indexOf(".")&&p.src.toLowerCase().split(".").pop()||"jpg",l=p.quality||80,t=await MediaLibraryBase.getPermissions();if(-1===t.perNum)return e(["permission fail",ErrorCode$1.USER_REJECT,t.perNum,t.dialogShownResults]);if(l&&"number"!=typeof l)return e(["compressImage fail, input parameter quality is illegal.",ErrorCode$1.PARAMETER_ERROR]);(100{console.info("AVPlayer seek succeeded, seek time is "+e),this.onSeekedCallback&&this.onSeekedCallback({})}),this.avPlayer.on("error",e=>{console.error(`Invoke avPlayer failed, code is ${e.code}, message is `+e.message),this.avPlayer.reset(),this.onErrorCallback&&this.onErrorCallback(e)}),this.avPlayer.on("stateChange",async(e,t)=>{switch(e){case"idle":console.info("AVPlayer state idle called."),this.stopFlag&&(this.avPlayer.url=this.tempSrc,this.stopFlag=!1);break;case"initialized":console.info("AVPlayerstate initialized called."),this.avPlayer.prepare().then(()=>{console.info("AVPlayer prepare succeeded."),this.onCanplayCallback&&this.onCanplayCallback({})},e=>{console.error(`Invoke prepare failed, code is ${e.code}, message is `+e.message)});break;case"prepared":console.info("AVPlayer state prepared called."),0===this.count&&this.autoplayS&&(this.avPlayer.play(),this.onPlayCallback&&this.onPlayCallback({}),this.startTimeS)&&(this.onSeekingCallback&&this.onSeekingCallback({}),this.avPlayer.seek(this.startTimeS)),this.count++,this.avPlayer.loop=this.tempLoop,this.avPlayer.setVolume(this.volumeS),this.avPlayer.setSpeed(this.playbackRateS);break;case"playing":console.info("AVPlayer state playing called."),this.avPlayer.loop=this.tempLoop,this.avPlayer.setVolume(this.volumeS),this.avPlayer.setSpeed(this.playbackRateS);break;case"paused":console.info("AVPlayer state paused called."),this.avPlayer.loop=this.tempLoop,this.avPlayer.setVolume(this.volumeS),this.avPlayer.setSpeed(this.playbackRateS);break;case"completed":console.info("AVPlayer state completed called."),this.onEndedCallback&&this.onEndedCallback({}),this.avPlayer.loop=this.tempLoop,this.avPlayer.setVolume(this.volumeS),this.avPlayer.setSpeed(this.playbackRateS);break;case"stopped":console.info("AVPlayer state stopped called."),this.avPlayer.reset(),this.stopFlag=!0;break;case"released":console.info("AVPlayer state released called.");break;default:console.info("AVPlayer state unknown called.")}}),this.avPlayer.on("timeUpdate",e=>{this.onTimeUpdateCallback&&this.onTimeUpdateCallback(e/1e3)}),this.avPlayer.on("bufferingUpdate",(e,t)=>{console.info(`[AdvancedAPI] avPlayer bufferingUpdate ${e} `+t),3===e&&0!==t&&(this.bufferedS=t,this.avPlayer.currentTime/1e3>=this.avPlayer.duration*t/1e5)&&this.onWaitingCallback&&this.onWaitingCallback({})}),this.avPlayer.on("audioInterrupt",e=>{console.info("[AdvancedAPI] audioInterrupt:"+JSON.stringify(e)),e.hintType===audio.InterruptHint.INTERRUPT_HINT_PAUSE&&(this.avPlayer.pause(),this.onPauseCallback)&&this.onPauseCallback({})}),this.avPlayer.on("endOfStream",()=>{console.info("[AdvancedAPI] rePlay:endOfStream success"),this.avPlayer.loop&&(this.avPlayer.play(),this.startTimeS)&&(this.onSeekingCallback&&this.onSeekingCallback({}),this.avPlayer.seek(this.startTimeS))})}get duration(){return this.avPlayer?this.avPlayer.duration/1e3:(console.error("[AdvancedAPI] avPlayer is not exist, get duration fail"),0)}get currentTime(){return this.avPlayer?this.avPlayer.currentTime/1e3:(console.error("[AdvancedAPI] avPlayer is not exist, get currentTime fail"),0)}get paused(){return this.avPlayer?this.avPlayer.state===StateType.PAUSED:(console.error("[AdvancedAPI] avPlayer is not exist, get paused fail"),!0)}get loop(){return this.tempLoop}set loop(e){"boolean"!=typeof e?console.error(`[AdvancedAPI] loop: ${e} is invalid`):(this.tempLoop=e,this.avPlayer&&[StateType.PREPARED,StateType.PLAYING,StateType.PAUSED,StateType.COMPLETED].includes(this.avPlayer.state)&&(console.info("current state is "+this.avPlayer.state+" can set loop"),this.avPlayer.loop=e))}get volume(){return this.volumeS}set volume(e){"number"!=typeof e?console.error(`[AdvancedAPI] volume: ${e} is invalid`):(this.volumeS=e,this.avPlayer&&[StateType.PREPARED,StateType.PLAYING,StateType.PAUSED,StateType.COMPLETED].includes(this.avPlayer.state)&&(console.info("current state is "+this.avPlayer.state+" can set volume"),this.avPlayer.setVolume(e)))}get autoplay(){return this.autoplayS}set autoplay(e){"boolean"!=typeof e?console.error(`[AdvancedAPI] autoplay: ${e} is invalid`):this.autoplayS=e}get startTime(){return this.startTimeS/1e3}set startTime(e){"number"!=typeof e?console.error(`[AdvancedAPI] startTIme: ${e} is invalid`):this.startTimeS=1e3*e}get src(){return this.avPlayer?this.avPlayer.url:(console.error("[AdvancedAPI] avPlayer is not exist, get src fail"),"")}set src(e){if("string"!=typeof e)console.error(`[AdvancedAPI] src: ${e} is invalid`);else if(this.avPlayer)if(e&&(e.startsWith("http:")||e.startsWith("https:")||e.startsWith("datashare:")||e.startsWith("internal://")))if(this.avPlayer.state!==StateType.IDLE)console.error("current state is "+this.avPlayer.state+" can not set url");else{let t;if(e.startsWith("http:")||e.startsWith("https:"))t=e;else if(e.startsWith("internal://"))try{var o=switchInternalToHapSandBox(e),a=fs.openSync(o,fs.OpenMode.READ_ONLY).fd;t="fd://"+a}catch(o){console.info(""+JSON.stringify(o))}else if(e.startsWith("datashare:"))try{var r=MediaLibraryBase.getMedia(),s=MediaLibraryBase.getFileKey(),i=MediaLibraryBase.getMediaType("AUDIO"),n={selections:s.MEDIA_TYPE+"= ?",selectionArgs:[i.toString()],uri:e};return void r.getFileAssets(n).then(e=>{e.getFirstObject().then(e=>{MediaLibraryBase.getFd(e).then(e=>{t="fd://"+e,this.avPlayer.url&&t!==this.avPlayer.url&&this.avPlayer.reset(),this.avPlayer.url=t})})})}catch(o){return void console.error(`[AdvancedAPI] src: ${e} is invalid`)}this.avPlayer.url&&t!==this.avPlayer.url&&this.avPlayer.reset(),this.avPlayer.url=t,this.tempSrc=t}else console.error(`[AdvancedAPI] src: ${e} is invalid`);else console.error("[AdvancedAPI] avPlayer is not exist, set src fail")}get buffered(){return this.avPlayer?this.avPlayer.duration*this.bufferedS/1e5:(console.error("[AdvancedAPI] avPlayer is not exist, get buffered fail"),0)}get playbackRate(){return this.playbackRateS}set playbackRate(e){"number"!=typeof e?console.error(`[AdvancedAPI] speed: ${e} is invalid`):(e=e<=.75?media.PlaybackSpeed.SPEED_FORWARD_0_75_X:.75t(["getVideoInfo is not support!"]))}saveVideoToPhotosAlbum(e){return new Promise(async(t,o)=>{var a,r,s,i=e.filePath;if("string"!=typeof i)return o(["filePath format is not supported.",ErrorCode$1.PARAMETER_ERROR]);if(console.debug("[AdvancedAPI] filePath:",i),isFileUri(i))r=getFdFromUriOrSandBoxPath(a=i),s=fs.statSync(r).size,s=new ArrayBuffer(s),FileioBase.ohosReadSync(r,s),r=await getFileAssetFromUri(a),r="VIDEO_"+(new Date).getTime()+"_"+r.displayName,t({path:await saveMedia(photoAccessHelper.PhotoType.VIDEO,r,a,s)});else{if(isSandboxPath(i)){let e=i;return e.startsWith("internal://")&&(e=switchInternalToHapSandBox(e)),fs.accessSync(e)&&(r=fs.openSync(e,fs.OpenMode.READ_ONLY))?(a=r.fd,s=fs.statSync(e).size,r=new ArrayBuffer(s),FileioBase.ohosReadSync(a,r),s="VIDEO_"+(new Date).getTime()+"_"+i.split("/").splice(-1,1).toString(),e=fileuri.getUriFromPath(e),void t({path:await saveMedia(photoAccessHelper.PhotoType.VIDEO,s,e,r)})):void o(["saveVideoToPhotosAlbum fail, src not exist.",ErrorCode$1.PARAMETER_ERROR])}o(["filePath format is not supported.",ErrorCode$1.PARAMETER_ERROR])}})}}let StateType$1={IDLE:"idle",PLAYING:"playing",PAUSED:"paused",STOPPED:"stopped",ERROR:"error"};function createAVSession(t){console.debug("[AdvancedAPI] createAVSession begin"),avSession.createAVSession(context,"player","audio").then(e=>{console.debug("[AdvancedAPI] createAVSession succeed"),t.avSession=e})}function destroyAVSession(e){console.debug("[AdvancedAPI] destroyAVSession begin"),null===e.avSession?console.debug("[AdvancedAPI] avSession is null"):e.avSession.destroy()}function startBackgroundTask(){AbilityBase.getAbilityInfo().then(e=>{e={wants:[{bundleName:e.bundleName,abilityName:e.name}],operationType:wantAgent.OperationType.START_ABILITY,requestCode:0,wantAgentFlags:[wantAgent.WantAgentFlags.UPDATE_PRESENT_FLAG]},wantAgent.getWantAgent(e).then(e=>backgroundTaskManager.startBackgroundRunning(context,backgroundTaskManager.BackgroundMode.AUDIO_PLAYBACK,e)).then(()=>{console.debug("[AdvancedAPI] start bg operation succeeded")}).catch(e=>{console.error("[AdvancedAPI] start bg operation failed Cause: "+e)})})}function stopBackgroundTask(){backgroundTaskManager.stopBackgroundRunning(context).then(()=>{console.debug("[AdvancedAPI] stop operation succeeded")}).catch(e=>{console.error("[AdvancedAPI] stop operation fail cause: "+JSON.stringify(e))})}class ASBGAudio{constructor(){this.backgroundAudioManager=new BackgroundAudioManager}}class BackgroundAudioManager{constructor(){this.bufferedS=0,this.avSession=null,this.startTimeS=0,this.onWaitingCallback=null,this.titleS=null,this.epnameS=null,this.singerS=null,this.coverImgUrlS=null,this.webUrlS=null,this.protocolS="http",this.onFinishCallback=null,this.tempSrc="",this.onCanplayCallback=null,this.onPlayCallback=null,this.onPauseCallback=null,this.onStopCallback=null,this.onTimeUpdateCallback=null,this.onErrorCallback=null,this.init()}init(){this.audioPlayer=media.createAudioPlayer(),this.audioPlayer.on("finish",()=>{destroyAVSession(this),stopBackgroundTask(),this.onFinishCallback&&this.onFinishCallback({})}),this.audioPlayer.on("dataLoad",()=>{this.onCanplayCallback&&this.onCanplayCallback({})}),this.audioPlayer.on("bufferingUpdate",(e,t)=>{console.info(`[AdvancedAPI] bgAudio bufferingUpdate ${e} `+t),3===e&&0!==t&&(this.bufferedS=t,this.audioPlayer.currentTime/1e3>=this.audioPlayer.duration*t/1e5)&&this.onWaitingCallback&&this.onWaitingCallback({})}),this.audioPlayer.on("audioInterrupt",e=>{console.info("[AdvancedAPI] audioInterrupt:"+JSON.stringify(e)),e.hintType===audio.InterruptHint.INTERRUPT_HINT_PAUSE&&this.audioPlayer.pause(),e.hintType===audio.InterruptHint.INTERRUPT_HINT_RESUME&&this.audioPlayer.play()}),this.audioPlayer.on("play",()=>{this.onPlayCallback&&this.onPlayCallback({})}),this.audioPlayer.on("pause",()=>{this.onPauseCallback&&this.onPauseCallback({})}),this.audioPlayer.on("timeUpdate",e=>{this.onTimeUpdateCallback&&this.onTimeUpdateCallback(e/1e3)}),this.audioPlayer.on("error",e=>{this.onErrorCallback&&this.onErrorCallback(e)})}get duration(){return this.audioPlayer.duration/1e3}get currentTime(){return this.audioPlayer.currentTime/1e3}get paused(){return this.audioPlayer.state===StateType$1.PAUSED}get src(){return this.audioPlayer.src}set src(t){if("string"!=typeof t)console.error(`[AdvancedAPI] src: ${t} is invalid`);else if(t&&(t.startsWith("http:")||t.startsWith("https:")||isFileUri(t)||isSandboxPath(t))){let e;if(t.startsWith("http:")||t.startsWith("https:"))e=t;else if(isFileUri(t)||isSandboxPath(t))try{var o=getFdFromUriOrSandBoxPath(t);e="fd://"+o}catch(e){console.info(""+JSON.stringify(e))}this.audioPlayer.src&&e!==this.audioPlayer.src&&this.audioPlayer.reset(),this.audioPlayer.src=e,this.tempSrc=t,this.audioPlayer.play(),this.startTimeS&&this.audioPlayer.seek(this.startTimeS),startBackgroundTask(),createAVSession(this)}else console.error(`[AdvancedAPI] src: ${t} is invalid`)}get startTime(){return this.startTimeS/1e3}set startTime(e){this.startTimeS=1e3*e}get buffered(){return this.audioPlayer.duration*this.bufferedS/1e5}get title(){return this.titleS}set title(e){this.titleS=e}get epname(){return this.epnameS}set epname(e){this.epnameS=e}get singer(){return this.singerS}set singer(e){this.singerS=e}get coverImgUrl(){return this.coverImgUrlS}set coverImgUrl(e){this.coverImgUrlS=e}get webUrl(){return this.webUrlS}set webUrl(e){this.webUrlS=e}get protocol(){return this.protocolS}set protocol(e){this.protocolS=e}play(){var e=this.audioPlayer.state;[StateType$1.PAUSED,StateType$1.STOPPED,StateType$1.IDLE].includes(e)&&(this.tempSrc&&""===this.audioPlayer.src&&(this.src=this.tempSrc),this.audioPlayer.play(),startBackgroundTask(),createAVSession(this))}pause(){var e=this.audioPlayer.state;StateType$1.PLAYING===e&&this.audioPlayer.pause()}stop(){var e=this.audioPlayer.state;[StateType$1.PAUSED,StateType$1.PLAYING].includes(e)&&(this.audioPlayer.stop(),this.onStopCallback&&this.onStopCallback({}),this.audioPlayer.release(),this.init(),destroyAVSession(this),stopBackgroundTask())}seek(e){var t=this.audioPlayer.state;[StateType$1.PAUSED,StateType$1.PLAYING].includes(t)&&this.audioPlayer.seek(1e3*e)}onCanplay(e){this.onCanplayCallback=e}onPlay(e){this.onPlayCallback=e}onPause(e){this.onPauseCallback=e}onStop(e){this.onStopCallback=e}onEnded(e){this.onFinishCallback=e}onTimeUpdate(e){this.onTimeUpdateCallback=e}onError(e){this.onErrorCallback=e}onPrev(e){console.info("ios only")}onNext(e){console.info("ios only")}onWaiting(e){this.onWaitingCallback=e}}class SecurityBase{static rsa(a,r){return new Promise(async(e,t)=>{var o;try{await(o=cryptoFramework.createMd(a)).update(r),e((await o.digest()).data)}catch(e){console.error("[QAFAPI]: rsa fail error code: "+e.code+", message is: "+e.message),t(e)}})}}class FileCallback{constructor({success:e,fail:t,complete:o}){checkDataType(e,!1,"function")&&(this.successFn=e),checkDataType(t,!1,"function")&&(this.failFn=t),checkDataType(o,!1,"function")&&(this.completeFn=o)}success(...e){if(this.successFn)try{this.successFn(...e)}catch(e){console.error(e)}if(this.completeFn)try{this.completeFn(...e)}catch(e){console.error(e)}}fail(...e){if(this.failFn)try{this.failFn(...e)}catch(e){console.error(e)}if(this.completeFn)try{this.completeFn(...e)}catch(e){console.error(e)}}}let openMode=fs.OpenMode,ERROR={PARAMETER_ERROR:1001},modeReflect={ax:"a","ax+":"a+",wx:"w","wx+":"w+"},ENCODING=["utf8","utf-8","ascii","base64","binary","hex","ucs2","ucs-2","utf16le","utf-16le","latin1"];function getOpenMode(e){let t;switch(e){case"a":t=openMode.CREATE|openMode.APPEND;break;case"a+":t=openMode.CREATE|openMode.READ_WRITE|openMode.APPEND;break;case"as":t=openMode.SYNC|openMode.CREATE|openMode.APPEND;break;case"as+":t=openMode.SYNC|openMode.CREATE|openMode.READ_WRITE|openMode.APPEND;break;case"r":t=openMode.READ_ONLY;break;case"r+":t=openMode.READ_WRITE;break;case"w":t=openMode.CREATE|openMode.WRITE_ONLY|openMode.TRUNC;break;case"w+":t=openMode.CREATE|openMode.READ_WRIT|openMode.TRUNC}return t}function getFileTypeMode(e){return e.isBlockDevice()?24576:e.isCharacterDevice()?8192:e.isDirectory()?16384:e.isFIFO()?4096:e.isFile()?32768:e.isSocket()?49152:e.isSymbolicLink()?40960:void 0}function mkdirRecursive(e,t){var o=t.shift();e=e||o?e+"/"+o:"",o&&!fs.accessSync(e)&&fs.mkdirSync(e),0{e?(console.debug("[AdvancedAPI] file access exist"),r.success({errMsg:"access:ok"})):r.fail({errMsg:"access:fail no such file or directory"})},e=>{console.debug("[AdvancedAPI] access failed with error message: %s, code = %d",e.message,e.code)}):r.fail({errMsg:"access:fail parameter error: parameter.path should be String",errno:ERROR$1.PARAMETER_ERROR})}accessSync(e){if(!checkDataType(e,!0,"string"))throw new Error("accessSync:fail path must be a string");if(!fs.accessSync(e))throw new Error("accessSync:fail no such file or directory")}appendFile({filePath:e,data:o,encoding:t=DEFAULT_ENCODING,success:a,fail:r,complete:s}){let i=new FileCallback({success:a,fail:r,complete:s});if(checkDataType(e,!0,"string"))if(checkDataType(o,!0,["string","arraybuffer"]))if(fs.accessSync(e)){let t=fs.openSync(e,fs.OpenMode.READ_WRITE|fs.OpenMode.APPEND);fs.write(t.fd,o).then(e=>{i.success({errMsg:"appendFile:ok"}),fs.closeSync(t)}).catch(e=>{console.error("[AdvancedAPI] appendFile failed with error message: "+e.message+", error code: "+e.code),i.fail({errMsg:"appendFile:fail "+e.message})})}else i.fail({errMsg:`appendFile:fail no such file or directory, open "${e}"`});else i.fail({errMsg:"access:fail parameter error: parameter.data should be String/ArrayBuffer",errno:ERROR$1.PARAMETER_ERROR});else i.fail({errMsg:"access:fail parameter error: parameter.filePath should be String",errno:ERROR$1.PARAMETER_ERROR})}appendFileSync(e,t,o=DEFAULT_ENCODING){if(!checkDataType(e,!0,"string"))throw new Error("access:fail parameter error: parameter.filePath should be String");if(!checkDataType(t,!0,["string","arraybuffer"]))throw new Error("access:fail parameter error: parameter.data should be String/ArrayBuffer");if(!fs.accessSync(e))throw new Error(`appendFile:fail no such file or directory, open "${e}"`);e=fs.openSync(e,fs.OpenMode.READ_WRITE|fs.OpenMode.APPEND),fs.writeSync(e.fd,t)}open({filePath:e,flag:t=DEFAULT_FLAG,success:o,fail:a,complete:r}){let s=new FileCallback({success:o,fail:a,complete:r});if(checkDataType(e,!0,"string")){if(FLAG.includes(t)||(t=DEFAULT_FLAG),Object.keys(modeReflect).includes(t)){if(fs.accessSync(e))return void s.fail({errMsg:"open:fail EXIST: file already exists"});console.debug("[AdvancedAPI] access fail"),t=modeReflect[t]}fs.open(e,getOpenMode(t),(e,t)=>{e?(console.error("[AdvancedAPI] open failed with error message: "+e.message+", error code: "+e.code),s.fail({errMsg:"open:fail "+e.message,errno:ERROR$1.NO_SUCH_FILE_OR_DIRECTORY})):s.success({fd:t.fd.toString(),errMsg:"open:ok"})})}else s.fail({errMsg:"open:fail parameter error: parameter.filePath should be String",errno:ERROR$1.PARAMETER_ERROR})}openSync({filePath:e,flag:t}){if(!checkDataType(e,!0,"string"))throw new Error("openSync:fail parameter error: parameter.filePath should be String");if(FLAG.includes(t)||(t=DEFAULT_FLAG),Object.keys(modeReflect).includes(t)){if(fs.accessSync(e))throw new Error("openSync:fail EXIST: file already exists");console.debug("[AdvancedAPI] access fail"),t=modeReflect[t]}return fs.openSync(e,getOpenMode(t)).fd.toString()}close({fd:e,success:t,fail:o,complete:a}){let r=new FileCallback({success:t,fail:o,complete:a});""!==e&&checkDataType(e,!0,"string")?(e=Number(e),isNaN(e)?r.fail({errMsg:"close:fail bad file descriptor"}):fs.close(e,e=>{e?r.fail({errMsg:"close:fail bad file descriptor"}):r.success({errMsg:"close:ok"})})):r.fail({errMsg:"close:fail invalid fd",errno:ERROR$1.PARAMETER_ERROR})}closeSync({fd:e}){if(""===e||!checkDataType(e,!0,"string"))throw new Error("closeSync:fail invalid fd");if(e=Number(e),isNaN(e))throw new Error("closeSync:fail invalid fd");fs.closeSync(e)}copyFile({srcPath:e,destPath:t,success:o,fail:a,complete:r}){let s=new FileCallback({success:o,fail:a,complete:r});if((o=checkPathExistence("copyFile","srcPath",e)).isValid)if((a=checkPath("copyFile","destPath",t)).isValid)if(fs.statSync(e).isDirectory())s.fail({errMsg:"copyFile: fail illegal operation on a directory, open: "+e});else{if(fs.accessSync(t)){if((r=fs.statSync(t)).isDirectory())t+=obtainFileName(e).fileName;else if(r.isFile()&&e!==t)return void s.fail({errMsg:"copyFile: fail copyFile failed"})}else if(r=obtainUpperPath(t),!fs.accessSync(r.upperPath))return void s.fail({errMsg:"copyFile: fail no such file or directory, open: "+t});fs.copyFile(e,t).then(()=>{s.success({errMsg:"copyFile: ok"})}).catch(e=>{s.fail({errMsg:`copyFile: failed with error message: ${e.message}, error code: `+e.code})})}else s.fail(a.checkMsg);else s.fail(o.checkMsg)}copyFileSync(e,t){var o=checkPathExistenceSync("copyFileSync","srcPath",e);if(!o.isValid)throw new Error(o.errMsg);if(!(o=checkPathSync("copyFileSync","destPath",t)).isValid)throw new Error(o.errMsg);if(fs.statSync(e).isDirectory())throw new Error("copyFileSync: fail illegal operation on a directory: "+e);if(fs.accessSync(t)){if((o=fs.statSync(t)).isDirectory()){var a=t.lastIndexOf("/");let e=t.substring(a);t.endsWith("/")&&(e=t.substring(t.lastIndexOf("/",t.length-2)+1,t.length-1)),t+=e}else if(o.isFile()&&e!==t)throw new Error("copyFileSync: fail copyFile failed")}else if(a=obtainUpperPath(t),!fs.accessSync(a.upperPath))throw new Error("copyFileSync: fail no such file or directory: "+t);try{fs.copyFileSync(e,t)}catch(e){throw new Error("copyFileSync: "+e.message)}}fstat({fd:e,success:t,fail:o,complete:a}){let r=new FileCallback({success:t,fail:o,complete:a});(t=checkFd("fstat",e)).isValid?(e=t.fd,fs.stat(e,(e,t)=>{e?r.fail({errMsg:`fstat: failed with error message: ${e.message}, error code: `+e.code}):(e=getFileTypeMode(t)|t.mode,r.success({stat:{mode:e,size:t.size,lastAccessedTime:t.atime,lastModifiedTime:t.mtime,isDirectory:()=>t.isDirectory(),isFile:()=>t.isFile()},errMsg:"fstat: ok"}))})):r.fail(t.checkMsg)}fstatSync({fd:t}){var e=checkFdSync("fstatSync",t);if(!e.isValid)throw new Error(e.errMsg);t=e.fd;try{let e=fs.statSync(t);return{stat:{mode:getFileTypeMode(e)|e.mode,size:e.size,lastAccessedTime:e.atime,lastModifiedTime:e.mtime,isDirectory:()=>e.isDirectory(),isFile:()=>e.isFile()}}}catch(e){throw new Error("fstatSync: "+e.message)}}ftruncate({fd:e,length:t,success:o,fail:a,complete:r}){let s=new FileCallback({success:o,fail:a,complete:r});(o=checkFd("ftruncate",e)).isValid?(e=o.fd,(!checkDataType(t,!0,"number")||t<0)&&(t=DEFAULT_LENGTH),fs.truncate(e,t).then(()=>{s.success({errMsg:"ftruncate: ok"})}).catch(e=>{s.fail({errMsg:`ftruncate: failed with error message: ${e.message}, error code: `+e.code})})):s.fail(o.checkMsg)}ftruncateSync({fd:e,length:t}){var o=checkFdSync("ftruncateSync",e);if(!o.isValid)throw new Error(o.errMsg);e=o.fd,(!checkDataType(t,!0,"number")||t<0)&&(t=DEFAULT_LENGTH);try{fs.truncateSync(e,t)}catch(e){throw new Error("ftruncateSync: "+e.message)}}mkdir({dirPath:e,recursive:t,success:o,fail:a,complete:r}){let s=new FileCallback({success:o,fail:a,complete:r});checkDataType(t,!1,"boolean")||(t=Boolean(t)),(o=checkPath("mkdir","dirPath",e)).isValid?fs.accessSync(e)?s.fail({errMsg:"mkdir: dirPath already exists: "+e}):t?(mkdirRecursive("",e.split("/")),s.success({errMsg:"mkdir: ok"})):(a=obtainUpperPath(e),fs.accessSync(a.upperPath)?fs.mkdir(e).then(()=>{s.success({errMsg:"mkdir: ok"})}).catch(e=>{s.fail({errMsg:`mkdir: failed with error message: ${e.message}, error code: `+e.code})}):s.fail({errMsg:"mkdir: failed"})):s.fail(o.checkMsg)}mkdirSync(e,t){checkDataType(t,!1,"boolean")||(t=Boolean(t));var o=checkPathSync("mkdirSync","dirPath",e);if(!o.isValid)throw new Error(o.errMsg);if(fs.accessSync(e))throw new Error("mkdirSync: dirPath already exists: "+e);if(!t&&!fs.accessSync(obtainUpperPath(e).upperPath))throw new Error("mkdirSync: fail, recursive is false and upper path does not exist");if(t)try{mkdirRecursive("",e.split("/"))}catch(e){throw new Error("mkdirSync: "+e.message)}else try{fs.mkdirSync(e)}catch(e){throw new Error("mkdirSync: "+e.message)}}read({fd:e,arrayBuffer:r,offset:t=DEFAULT_OFFSET,length:s,position:i,success:o,fail:a,complete:n}){let c=new FileCallback({success:o,fail:a,complete:n});if(!checkDataType(e,!0,"string")||""===e||isNaN(Number(e)))c.fail({errMsg:"read: fail invalid fd"});else if(e=Number(e),checkDataType(r,!0,"arraybuffer"))if((!checkDataType(t,!1,"number")||t<0)&&(t=Number(t),isNaN(t)||t<0)&&(t=DEFAULT_OFFSET),(!checkDataType(s,!1,"number")||s<0)&&(s=Number(s),isNaN(s)||s<0)&&(s=DEFAULT_LENGTH),(o=r.byteLength-t){var t=new Uint8Array(a);new Uint8Array(r).set(t,o),console.debug("[AdvancedAPI] the content of arrayBuffer: %s",String.fromCharCode.apply(null,new Uint8Array(a.slice(0,e)))),c.success({bytesRead:e,arrayBuffer:r,errMsg:"read: ok"})}).catch(e=>{c.fail({errMsg:`read: failed with error message: ${e.message},error code: `+e.code})})}else c.fail({errMsg:"read: fail invalid arrayBuffer: "+r})}readSync({fd:e,arrayBuffer:t,offset:o,length:a,position:r}){if(!checkDataType(e,!0,"string")||""===e||isNaN(Number(e)))throw new Error("readSync:fail invalid fd");if(e=Number(e),!checkDataType(t,!0,"arraybuffer"))throw new Error("readSync: fail invalid arrayBuffer");(!checkDataType(o,!1,"number")||o<0)&&(o=Number(o),isNaN(o)||o<0)&&(o=DEFAULT_OFFSET),(!checkDataType(a,!1,"number")||a<0)&&(a=Number(a),isNaN(a)||a<0)&&(a=DEFAULT_LENGTH);var s=t.byteLength-o;if(s{r.success({files:e,errMsg:"readdir: ok"})}).catch(e=>{r.fail({errMsg:`readdir: failed with error message: ${e.message}, error code: `+e.code})}):r.fail(t.checkMsg)}readdirSync(e){var t=checkPathExistence("readdirSync","dirPath",e);if(!t.isValid)throw new Error(t.errMsg);if(fs.statSync(e).isFile())throw new Error("readdirSync: fail not a directory: ${dirPath}");try{return{files:fs.listFileSync(e)}}catch(e){throw new Error("readdirSync: "+e.message)}}readFile({filePath:o,encoding:a,position:r=DEFAULT_POSITION,length:s,success:e,fail:t,complete:i}){o=isSandboxPath(o)?switchInternalToHapSandBox(o):o;let n=new FileCallback({success:e,fail:t,complete:i});if((e=checkPathExistence("readFile","filePath",o)).isValid)if((t=fs.statSync(o)).isDirectory())n.fail({errMsg:"readFile:fail not absolute path: "+o});else if((i=checkEncoding("readFile",a)).isValid)if(t=t.size,s=null==s?t:s,checkDataType(r,!1,"number"))if(checkDataType(s,!1,"number"))if(r<0||t{var e=a?buffer.from(t).toString(a):t;n.success({data:e,errMsg:"readFile:ok"})}).catch(e=>{n.fail({errMsg:`readFile:fail error message: ${e.message}, error code: `+e.code})}).finally(()=>{fs.closeSync(e)})}else n.fail({errMsg:"readFile:fail invalid length: "+s});else n.fail({errMsg:"readFile:fail invalid position: "+r});else n.fail({errMsg:i.checkMsg});else n.fail(e.checkMsg)}readFileSync(e,t,o=DEFAULT_POSITION,a){var r=checkPathExistenceSync("readFileSync","filePath",e=isSandboxPath(e)?switchInternalToHapSandBox(e):e);if(!r.isValid)throw new Error(r.errMsg);if((r=fs.statSync(e)).isDirectory())throw new Error("readFileSync:fail illegal operation on a directory, open: "+e);var s=checkEncoding("readFile",t);if(!s.isValid)throw new Error(s.checkMsg);if(s=r.size,a=null==a?s:a,!checkDataType(o,!1,"number"))throw new Error("readFileSync:fail invalid position: "+o);if(!checkDataType(a,!1,"number"))throw new Error("readFileSync:fail invalid length: "+a);if(o<0||s{s.success({errMsg:"rename: ok"})}).catch(e=>{s.fail({errMsg:`rename: failedwith error message: ${e.message}, error code: `+e.code})})}else s.fail(a.checkMsg);else s.fail(o.checkMsg)}renameSync(e,t){var o=checkPathExistenceSync("renameSync","oldPath",e);if(!o.isValid)throw new Error(o.errMsg);if(!(o=checkPathSync("renameSync","newPath",t)).isValid)throw new Error(o.errMsg);if(!(o=fs.accessSync(t))&&!fs.accessSync(obtainUpperPath(t).upperPath))throw new Error("renameSync: fail no such file or directory, open: "+t);if(o&&e!==t)throw new Error("renameSync: fail");try{fs.renameSync(e,t)}catch(e){throw new Error("renameSync: "+e.message)}}rmdir({dirPath:e,recursive:t,success:o,fail:a,complete:r}){let s=new FileCallback({success:o,fail:a,complete:r});checkDataType(t,!1,"boolean")||(t=Boolean(t)),(o=checkPathExistence("rmdir","dirPath",e)).isValid?fs.statSync(e).isDirectory()?!t&&fs.listFileSync(e).length?s.fail({errMsg:"rmdir: fail directory not empty"}):fs.rmdir(e).then(()=>{console.debug("[AdvanceAPI] rmdir succeed"),s.success({errMsg:"rmdir: ok"})}).catch(e=>{console.error(`[AdvanceAPI] rmdir failed with error message: ${e.message}, error code: `+e.code),s.fail({errMsg:"rmdir: failed"})}):s.fail({errMsg:"rmdir: fail no such directory, open: "+e}):s.fail(o.checkMsg)}rmdirSync(e,t){checkDataType(t,!1,"boolean")||(t=Boolean(t));var o=checkPathExistenceSync("rmdirSync","dirPath",e);if(!o.isValid)throw new Error(o.errMsg);if(!fs.statSync(e).isDirectory())throw new Error("rmdirSync: fail no such directory, open: "+e);if(!t&&0{console.debug("[AdvancedAPI] truncate: success, the read length is: %d",t),s.success({errMsg:"truncate: ok"})}).catch(e=>{console.error(`[AdvancedAPI] truncate: fail with error message: ${e.message}, error code: `+e.code),s.fail({errMsg:`truncate: failed with error message: ${e.message}, error code: `+e.code})})):s.fail(o.checkMsg)}truncateSync({filePath:e,length:t}){var o=checkPathExistenceSync("truncateSync","filePath",e);if(!o.isValid)throw new Error(o.errMsg);if(fs.statSync(e).isDirectory())throw new Error("truncateSync: fail, illegal operation on a directory, open: "+e);(!checkDataType(t,!0,"number")||t<0)&&(t=DEFAULT_LENGTH);try{fs.truncateSync(e,t)}catch(e){throw new Error("truncateSync: "+e.message)}}getFileInfo({filePath:e,success:t,fail:o,complete:a}){t=new FileCallback({success:t,fail:o,complete:a}),(e=isSandboxPath(e)?switchInternalToHapSandBox(e):e)&&checkDataType(e,!0,"string")?fs.accessSync(e)?(o=fs.statSync(e),t.success({size:o.size,errMsg:"getFileInfo:ok "})):t.fail({errMsg:"getFileInfo: fail no such file or directory : "+e}):t.fail({errMsg:"getFileInfo:fail invalid filePath "})}}class ASFile{constructor(){this.DIGESTALGORITHM_VALUES=["MD5","SHA1"],this.saveFileDir=context.filesDir+"/saveFiles",this.fileSystemManager=new FileSystemManager,this.init()}init(){try{FileioBase.ohosMkdirSync(this.saveFileDir)}catch(e){console.debug("[AdvancedAPI] %s 已存在",this.saveFileDir)}}saveFile(e){return new Promise(async(s,i)=>{var n=e.tempFilePath;if(n)try{let e=n.substr(n.lastIndexOf("/")),t=e&&e.split(".").pop(),o=(new Date).getTime(),a=(t&&(o+="."+t),getFdFromUriOrSandBoxPath(isSandboxPath(n)?fileuri.getUriFromPath(switchInternalToHapSandBox(n)):n)),r=this.saveFileDir+"/"+o;FileioBase.ohosCopy(a,r).then(()=>{console.debug("[AdvancedAPI] saveFile succeed"),s({savedFilePath:r})}).catch(e=>{console.error("[AdvancedAPI] saveFile failed with error message: "+e.message+", error code: "+e.code),i([e.message,ErrorCode$1.IO_ERROR])})}catch(e){console.error("[AdvancedAPI] tempFilePath does not exist"),i(["tempFilePath does not exist",ErrorCode$1.PARAMETER_ERROR])}else console.error("[AdvancedAPI] invalid tempFilePath."),i(["tempFilePath is required.",ErrorCode$1.PARAMETER_ERROR])})}getSavedFileList(){return new Promise((e,t)=>{var o=[],a=FileioBase.ohosOpendirSync(this.saveFileDir).ohosReadsync();for(let e=0;e{var o=a.filePath;o?(o=getFdFromUriOrSandBoxPath(isSandboxPath(o)?fileuri.getUriFromPath(switchInternalToHapSandBox(o)):o),e({createTime:(e=FileioBase.ohosStatSync(o)).mtime,size:e.size,errMsg:"getSavedFileInfo:ok"})):(console.error("[AdvancedAPI] filePath is required."),t(["filePath is required",ErrorCode$1.PARAMETER_ERROR]))})}removeSavedFile(r){return new Promise((e,t)=>{var o=r.filePath;if(o)try{var a=isSandboxPath(o)?switchInternalToHapSandBox(o):o;FileioBase.ohosUnlinkSync(a),e("success")}catch(e){t(["removeSavedFile is fail",ErrorCode$1.IO_ERROR])}else console.error("[AdvancedAPI] filePath is required."),t(["filePath is required",ErrorCode$1.PARAMETER_ERROR])})}getFileInfo(t){return new Promise((r,e)=>{let s=t.filePath,{digestAlgorithm:i="MD5"}=t;if(s){"string"==typeof i&&(i=i.toUpperCase()),this.DIGESTALGORITHM_VALUES.includes(i)||(console.error("[AdvancedAPI] digestAlgorithm is invalid."),i="MD5");try{let e=isSandboxPath(s)?fileuri.getUriFromPath(switchInternalToHapSandBox(s)):s,t=FileioBase.ohosOpenSync(e,2).fd,o=FileioBase.ohosStatSync(t),a=new ArrayBuffer(o.size);FileioBase.ohosReadSync(t,a),SecurityBase.rsa(i,{data:new Uint8Array(a)}).then(e=>{var t=new util.TextDecoder("utf-8",{ignoreBOM:!0});r({size:o.size,digest:t.decodeWithStream(e,{stream:!1})})})}catch(s){console.error("[AdvancedAPI] getFileInfo fail err = "+JSON.stringify(s)),e(["getFileInfo is fail",ErrorCode$1.IO_ERROR])}}else console.error("[AdvancedAPI] filePath is required."),e(["filePath is required",ErrorCode$1.PARAMETER_ERROR])})}openDocument(a){return new Promise((e,t)=>{var{showMenu:o=!1}=a;o&&console.error("[AdvancedAPI] showMenu do not support.")})}getFileSystemManager(){return this.fileSystemManager}}let name=settings.display.SCREEN_BRIGHTNESS_STATUS;class BrightnessBase{static ohoGetValue(){try{var e=settings.getValueSync(context,name,"1");return console.log("[AdvancedAPI] success to get brightness. value:"+e),Math.round(2.55*e),e}catch(e){console.log("[QAFAPI] Failed to get brightness. Cause:"+JSON.stringify(e))}}}_dec$2=jsMethod({alias:"getValue",common:!1,callback:!0}),_dec2$2=jsMethod({alias:"setValue",common:!1,callback:!0}),_dec3$1=jsMethod({alias:"setKeepScreenOn",common:!1,callback:!0}),_applyDecoratedDescriptor((_class$2=class{getValue(){return new Promise((o,t)=>{try{window.getLastWindow(context).then(e=>{let t=e.getWindowProperties().brightness;(!t||t<0)&&(t=Number(BrightnessBase.ohoGetValue())/255),e={value:Math.round(255*t)},console.debug("[QAFAPI] getValue success, brightness = "+JSON.stringify(e)),o([e])})}catch(e){t([["Failed to get brightness"]]),console.error("Failed to obtain the window properties. Cause: "+JSON.stringify(e))}})}setValue(e){return new Promise((o,a)=>{var r,s=e.value;if(s||0===s)if(isNumber(r=s)){let e=Math.floor(r),t=(e<0?e=1:255{e.setWindowBrightness(t,e=>{e.code?(a([["setWindowBrightness fail"]]),console.error("[QAFAPI] Failed to set the brightness. Cause: "+JSON.stringify(e))):(o("successed to set"),console.info("[QAFAPI] Succeeded in setting the brightness."))})})}catch(s){console.error("[QAFAPI] Failed to set setting of brightness. Cause:"+JSON.stringify(s)),a([["setWindowBrightness fail"]])}}else a([["inalid param",ErrorCode$1.PARAMETER_ERROR]]);else a([["inalid param",ErrorCode$1.PARAMETER_ERROR]])})}setKeepScreenOn(e){return new Promise((o,a)=>{if(e&&""!==e.keepScreenOn&&null!==e.keepScreenOn){let t=e.keepScreenOn;if("boolean"==typeof t)try{window.getLastWindow(context).then(e=>{e.setWindowKeepScreenOn(t,e=>{e.code?(console.error("[QAFAPI] Failed to set the screen to be always on. Cause: "+JSON.stringify(e)),a([["handling failed"]])):(o(["handling success"]),console.info("[QAFAPI] Succeeded in setting the screen to be always on."))})})}catch(e){console.error("[QAFAPI] Failed to set the screen to be always on. exception: "+JSON.stringify(e)),a([["handling failed"]])}else a([["inalid param",ErrorCode$1.PARAMETER_ERROR]])}else a([["inalid param",ErrorCode$1.PARAMETER_ERROR]])})}}).prototype,"getValue",[_dec$2],Object.getOwnPropertyDescriptor(_class$2.prototype,"getValue"),_class$2.prototype),_applyDecoratedDescriptor(_class$2.prototype,"setValue",[_dec2$2],Object.getOwnPropertyDescriptor(_class$2.prototype,"setValue"),_class$2.prototype),_applyDecoratedDescriptor(_class$2.prototype,"setKeepScreenOn",[_dec3$1],Object.getOwnPropertyDescriptor(_class$2.prototype,"setKeepScreenOn"),_class$2.prototype);let BrightnessBaseModule=_class$2;class ASBrightness extends BrightnessBaseModule{setScreenBrightness(e){if(console.info("[AdvancedAPI] params = "+JSON.stringify(e)),e&&void 0!==e.value&&"number"==typeof e.value){var t=e.value;if(t<=1&&0<=t)return this.setValue({value:Math.round(255*e.value)})}return new Promise((e,t)=>{t(["param is invalid.",ErrorCode$1.PARAMETER_ERROR])})}getScreenBrightness(){return this.getValue()}asSetKeepScreenOn(e){return this.setKeepScreenOn(e)}}class ASInterceptor{constructor(){this.apiLists={},this.globals=[]}checkApiName(e){return"addInterceptor"!==e&&"removeInterceptor"!==e}invoke(e,t){this.globals.forEach(e=>{"function"==typeof(e=e.invoke)&&e(...t)}),(this.apiLists[e]||[]).forEach(e=>{"function"==typeof(e=e.invoke)&&e(...t)})}success(e,o){let a=[];if(this.globals.forEach(e=>{"function"==typeof(e=e.success)&&a.push(e)}),(this.apiLists[e]||[]).forEach(e=>{"function"==typeof(e=e.success)&&a.push(e)}),a.length){let t=o&&JSON.parse(JSON.stringify(o));return a.forEach(e=>{e(...t)}),t}}fail(e,o){let a=[];if(this.globals.forEach(e=>{"function"==typeof(e=e.fail)&&a.push(e)}),(this.apiLists[e]||[]).forEach(e=>{"function"==typeof(e=e.fail)&&a.push(e)}),a.length){let t=o&&JSON.parse(JSON.stringify(o));return a.forEach(e=>{e(...t)}),t}}complete(e,o){let a=[];if(this.globals.forEach(e=>{"function"==typeof(e=e.complete)&&a.push(e)}),(this.apiLists[e]||[]).forEach(e=>{"function"==typeof(e=e.complete)&&a.push(e)}),a.length){let t=o&&JSON.parse(JSON.stringify(o));return a.forEach(e=>{e(...t)}),t}}returnValue(e,t){this.globals.forEach(e=>{"function"==typeof(e=e.returnValue)&&e(t)}),(this.apiLists[e]||[]).forEach(e=>{"function"==typeof(e=e.returnValue)&&e(t)})}}let SCAN_TYPE_AS_TO_HM={barCode:null==scanCore?void 0:scanCore.ScanType.ONE_D_CODE,qrCode:null==scanCore?void 0:scanCore.ScanType.TWO_D_CODE,datamatrix:null==scanCore?void 0:scanCore.ScanType.DATAMATRIX_CODE,pdf417:null==scanCore?void 0:scanCore.ScanType.PDF417_CODE};class ASScan{scanCode(i={}){return new Promise((t,o)=>{var{onlyFromCamera:e=!1,hideAlbum:a=!1,scanType:r=[]}=i,s=[];for(let e=0;e{t({result:e.originalValue,scanType:this.scanTypeHmToAs(e.scanType),rawData:gBase64.btoa(e.originalValue),charSet:"utf-8"})}).catch(e=>{o(["scanCode fail!",ErrorCode$1.COMMON_ERROR])})}catch(e){o(["scanCode fail!",ErrorCode$1.COMMON_ERROR])}}else o(["Parameter hideAlbum invalid!",ErrorCode$1.PARAMETER_ERROR]);else o(["Parameter onlyFromCamera invalid!",ErrorCode$1.PARAMETER_ERROR])})}scanTypeHmToAs(e){let t="UNKNOWN";switch(e){case scanCore.ScanType.DATAMATRIX_CODE:t="DATA_MATRIX";break;case scanCore.ScanType.PDF417_CODE:t="PDF_417";break;case scanCore.ScanType.AZTEC_CODE:t="AZTEC";break;case scanCore.ScanType.CODABAR_CODE:t="CODABAR";break;case scanCore.ScanType.CODE39_CODE:t="CODE_39";break;case scanCore.ScanType.CODE93_CODE:t="CODE_93";break;case scanCore.ScanType.CODE128_CODE:t="CODE_128";break;case scanCore.ScanType.EAN8_CODE:t="EAN_8";break;case scanCore.ScanType.EAN13_CODE:t="EAN_13";break;case scanCore.ScanType.ITF14_CODE:t="ITF";break;case scanCore.ScanType.QR_CODE:t="QR_CODE";break;case scanCore.ScanType.UPC_A_CODE:t="UPC_A";break;case scanCore.ScanType.UPC_E_CODE:t="UPC_E";break;case scanCore.ScanType.MULTIFUNCTIONAL_CODE:t="MULTIFUNCTIONAL";break;case scanCore.ScanType.ONE_D_CODE:t="CODABAR";break;case scanCore.ScanType.TWO_D_CODE:t="QR_CODE"}return t}}let asModulesMap=new Map,moduleInstance=(asModulesMap.set("ASDevice",ASDevice),asModulesMap.set("ASLocation",ASLocation),asModulesMap.set("ASPhone",ASPhone),asModulesMap.set("ASRequest",ASRequest),asModulesMap.set("ASRouter",ASRouter),asModulesMap.set("ASBluetooth",ASBluetooth),asModulesMap.set("ASWifi",ASWifi),asModulesMap.set("ASAuthentication",ASAuthentication),asModulesMap.set("ASAccelerometer",ASAccelerometer),asModulesMap.set("ASCompass",ASCompass),asModulesMap.set("ASGyroscope",ASGyroscope),asModulesMap.set("ASContact",ASContact),asModulesMap.set("ASVibrator",ASVibrator),asModulesMap.set("ASCapture",ASCapture),asModulesMap.set("ASKeyboard",ASKeyboard),asModulesMap.set("ASImage",ASImage),asModulesMap.set("ASBrightness",ASBrightness),asModulesMap.set("ASFile",ASFile),asModulesMap.set("ASAudio",ASAudio),asModulesMap.set("ASBGAudio",ASBGAudio),asModulesMap.set("ASVideo",ASViedo),asModulesMap.set("ASInterceptor",ASInterceptor),asModulesMap.set("ASScan",ASScan),{});function requireAPI$1(e){var t;return moduleInstance[e]||(console.debug("[AdvancedAPI] create %s",e),t=asModulesMap.get(e),moduleInstance[e]=new t),moduleInstance[e]}class CallbackManager{constructor(e){this.lastCallbackId=0,this.callbacks=[]}add(e){return this.lastCallbackId++,(this.callbacks[this.lastCallbackId]=e).__callbackId=this.lastCallbackId,this.lastCallbackId}consume(e,t,o){var a=this.callbacks[e];return void 0===o||!1===o?this.callbacks[e]=void 0:a.isKeepAlive=!0,"function"==typeof a?a(t):new Error(`invalid callback id "${e}"`)}close(){this.callbacks=this.callbacks.map(e=>{})}}let callbackManager=new CallbackManager;function interceptCallback(e,a,t=!0,o=!0){if(!(t||0!==e.length&&o))return{args:e};let r=e[0],s={},i=!1;if("object"==typeof r&&"[object object]"===Object.prototype.toString.call(r).toLowerCase()&&1===e.length)for(var n in r){var c=r[n];"function"==typeof c?s[n]=c:i=!0}else i=!0;"function"==typeof r&&(t=!1,r.isConnected?r.cb&&(e[0]=r.cb.id):(((o=e=>{r.apply(null,e.arguments)}).originFn=r).cb=o,e[0]=o));let l;var d,o=Object.keys(s).length;if(t&&o<=0){class h{constructor(){this.promise=new Promise((e,t)=>{this.reject=t,this.resolve=e})}}l=new h}return(0{let t=s[e.method];advancedResult(a,e);var o=triggerMethodIntercept(a,e.method,e.arguments)||e.arguments,{ignoreComplete:o=!1}=(void 0!==t&&t.apply(null,o),e);o||(o=triggerMethodIntercept(a,"complete",e.arguments)||e.arguments,void 0!==(t=s.complete)&&t.apply(null,o)),l&&(o=(o=e.arguments)&&0normalize(e))),r&&r.cb&&(r.isConnected=!0),{args:e,promise:l,needPromise:t}}function normalize(e){var t;return"function"==typeof e?(t=callbackManager.add(e),e.id=t):e}function advancedResult(e,t){var o;"success"===t.method?(t.arguments[0]&&"object"==typeof t.arguments[0]||(t.arguments[0]={}),void 0===(o=t.arguments[0]).errMsg&&(o.errMsg=e+":ok"),void 0===o.errCode&&(o.errCode=0)):"fail"===t.method&&(o=t.arguments||[],t.arguments=[{moduleName:""+e,errMsg:e+":fail:"+o.shift(),errCode:o.shift(),grantStatus:o.shift(),dialogShownResults:o.shift()}])}function triggerMethodIntercept(e,t,o){var a=requireAPI("ASInterceptor");if("function"==typeof(t=a[t]))return t.call(a,e,o)}class JSCallback{constructor(e){this.id=e.id,this._valid=!0}invoke(e){this._valid?callbackManager.consume(this.id,e,e.ifKeepAlive):console.error(`[AdvancedAPI] callback ${this.id} had be destroyed.`)}invokeAndKeepAlive(e){this._valid?callbackManager.consume(this.id,e,!0):console.error(`[AdvancedAPI] callback ${this.id} had be destroyed.`)}destroy(){this.id=void 0,this._valid=!1}}let jsCallbackMap=new Map;function getSystemInfoSync(){return console.debug("[AdvancedAPI] start getSystemInfoSync"),requireAPI("ASDevice").getSystemInfoSync()}function getDeviceInfo(...e){return console.debug("[AdvancedAPI] start getDeviceInfo"),e.pop(),e=requireAPI("ASDevice"),console.debug("[AdvancedAPI] device.getInfo"),e=e.getDeviceInfo()}function getWindowInfo(...e){return console.debug("[AdvancedAPI] start getWindowInfo"),e.pop(),requireAPI("ASDevice").getWindowInfo()}function getAppBaseInfo(...e){return console.debug("[AdvancedAPI] start getAppBaseInfo"),e.pop(),requireAPI("ASDevice").getAppBaseInfo()}function getAppAuthorizeSetting(...e){return console.debug("[AdvancedAPI] start getAppAuthorizeSetting"),e.pop(),requireAPI("ASDevice").getAppAuthorizeSetting()}function getSystemSetting(...e){return console.debug("[AdvancedAPI] start getSystemSetting"),e.pop(),e=requireAPI("ASDevice"),console.debug("[AdvancedAPI] device.getSystemSetting"),e=e.getSystemSetting()}function openAppAuthorizeSetting(...e){console.debug("[AdvancedAPI] start getSystemSetting");var e=e.pop(),t=requireAPI("ASDevice");try{t.openAppAuthorizeSetting(),e.invoke(Result.success("success"))}catch(t){e.invoke(Result.fail(["fail"],201))}}function navigateTo(...e){let t=e.pop();e=e.pop()||{},requireAPI("ASRouter").navigateTo(e).then(e=>{t.invoke(Result.success(e))},e=>{t.invoke(Result.fail(e))})}function redirectTo(...e){let t=e.pop();e=e.pop()||{},requireAPI("ASRouter").redirectTo(e).then(e=>{t.invoke(Result.success(e))},e=>{t.invoke(Result.fail(e))})}function navigateBack(...e){let t=e.pop();e=e.pop()||{},requireAPI("ASRouter").navigateBack(e).then(e=>{t.invoke(Result.success(e))},e=>{t.invoke(Result.fail(e))})}function getLocation(...e){console.debug("[AdvancedAPI] start getLocation");let o=e.pop();var e=e.pop(),t=requireAPI("ASLocation");console.debug("[AdvancedAPI] geolocation.getLocation"),t.getLocation(e).then(e=>{console.debug("[AdvancedAPI] geolocation.getLocation success"),o.invoke(Result.success(e))},(e,t)=>{console.debug("[AdvancedAPI] geolocation.getLocation fail"),o.invoke(Result.fail(e))})}function onLocationChange(...e){console.debug("[AdvancedAPI] start onLocationChange"),e=e.pop(),requireAPI("ASLocation").onLocationChange(e)}function offLocationChange(...e){console.debug("[AdvancedAPI] start offLocationChange");let t=e.pop();(e=requireAPI("ASLocation")).offLocationChange(t),e.getLocation({timeout:5e3,coordType:"wgs86"}).then(e=>{console.debug("[AdvancedAPI] geolocation.offLocationChange callback"),t.invokeAndKeepAlive(Result.success(e))},e=>{t.invokeAndKeepAlive(Result.fail([e[0][0],e[0][1]]))})}function onLocationChangeError(...e){console.debug("[AdvancedAPI] start onLocationChangeError");let t=e.pop();requireAPI("ASLocation").onLocationChangeError(e=>{console.debug("[AdvancedAPI] geolocation.onLocationChange success"),t.invokeAndKeepAlive(Result.callback(e))})}function offLocationChangeError(...e){console.debug("[AdvancedAPI] start offLocationChangeError"),e=e.pop(),requireAPI("ASLocation").offLocationChangeError(),e.invoke(Result.success())}function startLocationUpdate(...e){console.debug("[AdvancedAPI] start startLocationUpdate");let o=e.pop();requireAPI("ASLocation").startLocationUpdate().then(e=>{console.debug("[AdvancedAPI] geolocation.startLocationUpdate success"),o.invoke(Result.success(e))},(e,t)=>{console.debug("[AdvancedAPI] geolocation.startLocationUpdate fail"),o.invoke(Result.fail([e[0][0],e[0][1]]))})}function startLocationUpdateBackground(...e){console.debug("[AdvancedAPI] start startLocationUpdateBackground");let o=e.pop();requireAPI("ASLocation").startLocationUpdateBackground().then(e=>{console.debug("[AdvancedAPI] geolocation.startLocationUpdateBackground success"),o.invoke(Result.success(e))},(e,t)=>{console.debug("[AdvancedAPI] geolocation.startLocationUpdateBackground fail"),o.invoke(Result.fail([e[0][0],e[0][1]]))})}function stopLocationUpdate(...e){console.debug("[AdvancedAPI] start stopLocationUpdate");let o=e.pop();requireAPI("ASLocation").stopLocationUpdate(o).then(e=>{console.debug("[AdvancedAPI] geolocation.stopLocationUpdate success"),o.invoke(Result.success(e))},(e,t)=>{console.debug("[AdvancedAPI] geolocation.stopLocationUpdate fail"),o.invoke(Result.fail([e[0][0],e[0][1]]))})}function makePhoneCall(...e){let t=e.pop();e=e.pop(),requireAPI("ASPhone").makePhoneCall(e).then(()=>{t.invoke(Result.success())},e=>{console.error("[AdvancedAPI] start makePhoneCall fail"),t.invoke(Result.fail([e,-1]))})}function request(...e){var t=e.pop(),e=e.pop(),o=requireAPI("ASRequest"),o=(console.debug("[AdvancedAPI] request"),o.request(e));if(!e||e.success||e.fail||e.complete)return e||t.invoke(Result.fail(["illegal params",-1])),o;t.invoke(Result.success(o))}function uploadFile(...e){var t=e.pop(),e=e.pop(),o=requireAPI("ASRequest"),o=(console.debug("[AdvancedAPI] uploadFile"),o.uploadFile(e));if(!e||e.success||e.fail||e.complete)return e||t.invoke(Result.fail(["illegal params",-1])),o;t.invoke(Result.success(o))}function downloadFile(...e){var t=e.pop(),e=e.pop(),o=requireAPI("ASRequest"),o=(console.debug("[AdvancedAPI] downloadFile"),o.downloadFile(e));if(!e||e.success||e.fail||e.complete)return e||t.invoke(Result.fail(["illegal params",-1])),o;t.invoke(Result.success(o))}function openBluetoothAdapter(...e){let t=e.pop();requireAPI("ASBluetooth").openBluetoothAdapter().then(e=>{t.invoke(Result.success(e))},e=>{t.invoke(Result.fail(...e))})}function closeBluetoothAdapter(...e){let t=e.pop();requireAPI("ASBluetooth").closeBluetoothAdapter().then(e=>{t.invoke(Result.success(e))},e=>{t.invoke(Result.fail(...e))})}function startBluetoothDevicesDiscovery(...e){let t=e.pop();e=e.pop(),requireAPI("ASBluetooth").startBluetoothDevicesDiscovery(e).then(e=>{t.invoke(Result.success(e))},e=>{t.invoke(Result.fail(...e))})}function stopBluetoothDevicesDiscovery(...e){let t=e.pop();requireAPI("ASBluetooth").stopBluetoothDevicesDiscovery().then(e=>{t.invoke(Result.success(e))},e=>{t.invoke(Result.fail(...e))})}function onBluetoothDeviceFound(...e){e=e.pop(),requireAPI("ASBluetooth").onBluetoothDeviceFound(e)}function offBluetoothDeviceFound(...e){e=e.pop(),requireAPI("ASBluetooth").offBluetoothDeviceFound(e)}function onBluetoothAdapterStateChange(...e){e=e.pop(),requireAPI("ASBluetooth").onBluetoothAdapterStateChange(e)}function offBluetoothAdapterStateChange(...e){e=e.pop(),requireAPI("ASBluetooth").offBluetoothAdapterStateChange(e)}function getBluetoothDevices(...e){let t=e.pop();requireAPI("ASBluetooth").getBluetoothDevices().then(e=>{e=e&&e[0]&&e[0][0]||{},t.invoke(Result.success(e))},e=>{console.info("[AdvancedAPI] getBluetoothDevices fail"+JSON.stringify(e)),t.invoke(Result.fail(...e))})}function getConnectedBluetoothDevices(...e){let t=e.pop();e=e.pop(),requireAPI("ASBluetooth").getConnectedBluetoothDevices(e).then(e=>{console.info("[AdvancedAPI] getConnectedBluetoothDevices success"+JSON.stringify(e)),t.invoke(Result.success(e))},e=>{console.info("[AdvancedAPI] getConnectedBluetoothDevices fail"+JSON.stringify(e)),t.invoke(Result.fail(...e))})}function getBluetoothAdapterState(...e){let t=e.pop();requireAPI("ASBluetooth").getBluetoothAdapterState().then(e=>{t.invoke(Result.success(e))},e=>{t.invoke(Result.fail(...e))})}function setBLEMTU(...e){let t=e.pop();e=e.pop(),requireAPI("ASBluetooth").asSetBLEMTU(e).then(e=>{t.invoke(Result.success(e))},e=>{t.invoke(Result.fail(...e))})}function writeBLECharacteristicValue(...e){let t=e.pop();e=e.pop(),requireAPI("ASBluetooth").asWriteBLECharacteristicValue(e).then(e=>{t.invoke(Result.success(e))},e=>{t.invoke(Result.fail(...e))})}function readBLECharacteristicValue(...e){let t=e.pop();e=e.pop(),requireAPI("ASBluetooth").asReadBLECharacteristicValue(e).then(e=>{t.invoke(Result.success(e))},e=>{t.invoke(Result.fail(...e))})}function onBLEConnectionStateChange(...e){e=e.pop(),requireAPI("ASBluetooth").asOnBLEConnectionStateChange(e)}function offBLEConnectionStateChange(...e){e=e.pop(),requireAPI("ASBluetooth").asOffBLEConnectionStateChange(e)}function onBLECharacteristicValueChange(...e){e=e.pop(),requireAPI("ASBluetooth").asOnBLECharacteristicValueChange(e)}function offBLECharacteristicValueChange(...e){e=e.pop(),requireAPI("ASBluetooth").asOffBLECharacteristicValueChange(e)}function notifyBLECharacteristicValueChange(...e){let t=e.pop();e=e.pop(),requireAPI("ASBluetooth").asNotifyBLECharacteristicValueChange(e).then(e=>{t.invoke(Result.success(e))},e=>{t.invoke(Result.fail(...e))})}function getBLEDeviceServices(...e){let t=e.pop();e=e.pop(),requireAPI("ASBluetooth").asGetBLEDeviceServices(e).then(e=>{t.invoke(Result.success(e[0][0]))},e=>{t.invoke(Result.fail(...e))})}function getBLEDeviceRSSI(...e){let t=e.pop();e=e.pop(),requireAPI("ASBluetooth").asGetBLEDeviceRSSI(e).then(e=>{t.invoke(Result.success(e))},e=>{t.invoke(Result.fail(...e))})}function getBLEDeviceCharacteristics(...e){console.debug("[AdvancedAPI] enter getBLEDeviceCharacteristics");let t=e.pop();e=e.pop(),requireAPI("ASBluetooth").asGetBLEDeviceCharacteristics(e).then(e=>{t.invoke(Result.success(e[0]))},e=>{t.invoke(Result.fail(...e))})}function createBLEConnection(...e){let t=e.pop();var{deviceId:e,timeout:o}=e.pop()||{};requireAPI("ASBluetooth").asCreateBLEConnection({deviceId:e,timeout:o}).then(e=>{t.invoke(Result.success(e))},e=>{t.invoke(Result.fail(...e))})}function closeBLEConnection(...e){let t=e.pop();e=e.pop(),requireAPI("ASBluetooth").asCloseBLEConnection({deviceId:e?e.deviceId:void 0}).then(e=>{t.invoke(Result.success(e))},e=>{t.invoke(Result.fail(...e))})}function startWifi(...e){let t=e.pop();requireAPI("ASWifi").startWifi().then(e=>{t.invoke(Result.success(e))},e=>{t.invoke(Result.fail(e))})}function stopWifi(...e){let t=e.pop();requireAPI("ASWifi").stopWifi().then(e=>{t.invoke(Result.success(e))},e=>{t.invoke(Result.fail(e))})}function getConnectedWifi(...e){let t=e.pop();e=e.pop(),requireAPI("ASWifi").getConnectedWifi(e).then(e=>{t.invoke(Result.success(e))},e=>{t.invoke(Result.fail(e))})}function getWifiList(...e){let t=e.pop();e=e.pop(),requireAPI("ASWifi").getWifiList(e).then(e=>{t.invoke(Result.success(e))},e=>{t.invoke(Result.fail(e))})}function onGetWifiList(...e){e=e.pop(),requireAPI("ASWifi").onGetWifiList(e)}function offGetWifiList(...e){e=e.pop(),requireAPI("ASWifi").offGetWifiList(e)}function connectWifi(...e){let t=e.pop();e=e.pop(),requireAPI("ASWifi").connectWifi(e).then(e=>{t.invoke(Result.success(e))},e=>{t.invoke(Result.fail(e))})}function onWifiConnected(...e){e=e.pop(),requireAPI("ASWifi").onWifiConnected(e)}function offWifiConnected(...e){e=e.pop(),requireAPI("ASWifi").offWifiConnected(e)}function onWifiConnectedWithPartialInfo(...e){e=e.pop(),requireAPI("ASWifi").onWifiConnectedWithPartialInfo(e)}function offWifiConnectedWithPartialInfo(...e){e=e.pop(),requireAPI("ASWifi").offWifiConnectedWithPartialInfo(e)}function startSoterAuthentication(...e){console.debug("[AdvancedAPI] start startSoterAuthentication");let t=e.pop();e=e.pop(),console.debug("[AdvancedAPI] params = %s",JSON.stringify(e)),requireAPI("ASAuthentication").start(e).then(e=>{t.invoke(Result.success(e))},e=>{t.invoke(Result.fail(e))})}function checkIsSupportSoterAuthentication(...e){console.debug("[AdvancedAPI] start checkIsSupportSoterAuthentication");let t=e.pop();requireAPI("ASAuthentication").getSupportedType().then(e=>{t.invoke(Result.success(e))},e=>{t.invoke(Result.fail(e))})}function checkIsSoterEnrolledInDevice(...e){console.debug("[AdvancedAPI] start checkIsSoterEnrolledInDevice");let t=e.pop();e=e.pop(),console.debug("[AdvancedAPI] params = %s",JSON.stringify(e)),requireAPI("ASAuthentication").isEnrolled(e).then(e=>{t.invoke(Result.success(e))},e=>{t.invoke(Result.fail(e))})}function onAccelerometerChange(...e){console.debug("[AdvancedAPI] start onAccelerometerChange"),e=e.pop(),requireAPI("ASAccelerometer").onAccelerometerChange(e).then(e=>{console.debug("[AdvancedAPI] onAccelerometerChange success")},(e,t)=>{console.debug("[AdvancedAPI] onAccelerometerChange fail errMsg = %o, code = %d",e,t)})}function offAccelerometerChange(...e){console.debug("[AdvancedAPI] start offAccelerometerChange"),e=e.pop(),requireAPI("ASAccelerometer").offAccelerometerChange(e).then(e=>{console.debug("[AdvancedAPI] offAccelerometerChange success")},(e,t)=>{console.debug("[AdvancedAPI] offAccelerometerChange fail errMsg = %o, code = %d",e,t)})}function startAccelerometer(...e){console.debug("[AdvancedAPI] start startAccelerometer");let o=e.pop();requireAPI("ASAccelerometer").startAccelerometer(e[0]).then(e=>{console.debug("[AdvancedAPI] startAccelerometer success"),o.invoke(Result.success(e))},(e,t)=>{console.debug("[AdvancedAPI] startAccelerometer fail errMsg = %o, code = %d",e,t),o.invoke(Result.fail([e,t]))})}function stopAccelerometer(...e){console.debug("[AdvancedAPI] start stopAccelerometer");let o=e.pop();requireAPI("ASAccelerometer").stopAccelerometer().then(e=>{console.debug("[AdvancedAPI] startAccelerometer success"),o.invoke(Result.success(e))},(e,t)=>{console.debug("[AdvancedAPI] startAccelerometer fail"),o.invoke(Result.fail([e,t]))})}function onCompassChange(...e){console.debug("[AdvancedAPI] start onCompassChange"),e=e.pop(),requireAPI("ASCompass").onCompassChange(e).then(e=>{console.debug("[AdvancedAPI] onCompassChange success")},(e,t)=>{console.debug("[AdvancedAPI] onCompassChange fail errMsg = %o, code = %d",e,t)})}function offCompassChange(...e){console.debug("[AdvancedAPI] start offCompassChange"),e=e.pop(),requireAPI("ASCompass").offCompassChange(e).then(e=>{console.debug("[AdvancedAPI] offCompassChange success")},(e,t)=>{console.debug("[AdvancedAPI] offCompassChange fail errMsg = %o, code = %d",e,t)})}function startCompass(...e){console.debug("[AdvancedAPI] start startCompass");let o=e.pop();requireAPI("ASCompass").startCompass().then(e=>{console.debug("[AdvancedAPI] startCompass success"),o.invoke(Result.success(e))},(e,t)=>{console.debug("[AdvancedAPI] startCompass fail"),o.invoke(Result.fail([e,t]))})}function stopCompass(...e){console.debug("[AdvancedAPI] start stopCompass");let o=e.pop();requireAPI("ASCompass").stopCompass().then(e=>{console.debug("[AdvancedAPI] stopCompass success"),o.invoke(Result.success(e))},(e,t)=>{console.debug("[AdvancedAPI] stopCompass fail"),o.invoke(Result.fail([e,t]))})}function onGyroscopeChange(...e){console.debug("[AdvancedAPI] start onGyroscopeChange"),e=e.pop(),requireAPI("ASGyroscope").onGyroscopeChange(e).then(e=>{console.debug("[AdvancedAPI] onGyroscopeChange success")},(e,t)=>{console.debug("[AdvancedAPI] onGyroscopeChange fail errMsg = %o, code = %d",e,t)})}function startGyroscope(...e){console.debug("[AdvancedAPI] start startCompass");let o=e.pop();requireAPI("ASGyroscope").startGyroscope(e[0]).then(e=>{console.debug("[AdvancedAPI] startCompass success"),o.invoke(Result.success(e))},(e,t)=>{console.debug("[AdvancedAPI] startCompass fail errMsg = %o, code = %d",e,t),o.invoke(Result.fail([e,t]))})}function stopGyroscope(...e){console.debug("[AdvancedAPI] start stopGyroscope");let o=e.pop();requireAPI("ASGyroscope").stopGyroscope().then(e=>{console.debug("[AdvancedAPI] stopGyroscope success"),o.invoke(Result.success(e))},(e,t)=>{console.debug("[AdvancedAPI] stopGyroscope fail errMsg = %o, code = %d",e,t),o.invoke(Result.fail([e,t]))})}function addPhoneContact(...e){let t=e.pop();e=e.pop()||{},requireAPI("ASContact").addPhoneContact(e).then(e=>{t.invoke(Result.success(e))},e=>{t.invoke(Result.fail(e))})}function vibrate(...e){let t=e.pop();requireAPI("ASVibrator").vibrate().then(e=>{t.invoke(Result.success(e))},e=>{t.invoke(Result.fail(e))})}function vibrateLong(...e){let t=e.pop();requireAPI("ASVibrator").vibrateLong().then(e=>{t.invoke(Result.success(e))},e=>{t.invoke(Result.fail(e))})}function vibrateShort(...e){let t=e.pop();requireAPI("ASVibrator").vibrateShort().then(e=>{t.invoke(Result.success(e))},e=>{t.invoke(Result.fail(e))})}function onUserCaptureScreen(...e){e=e.pop(),requireAPI("ASCapture").onUserCaptureScreen(e)}function offUserCaptureScreen(...e){e=e.pop(),requireAPI("ASCapture").offUserCaptureScreen(e)}function hideKeyboard(...e){let t=requireAPI("ASKeyboard"),o=e.pop();t.hideKeyboard().then(()=>{console.debug("[AdvancedAPI] hideKeyboard success"),o.invoke(Result.success())},(e,t)=>{console.debug("[AdvancedAPI] hideKeyboard fail, code: %d, error: %s",t,e),o.invoke(Result.fail())})}function onKeyboardHeightChange(...e){e=e.pop(),requireAPI("ASKeyboard").onKeyboardHeightChange(e)}function offKeyboardHeightChange(...e){e=e.pop(),requireAPI("ASKeyboard").offKeyboardHeightChange(e)}function login(...e){let t=e.pop();var e=e.pop(),o=requireAPI("ASAccount");console.debug("[AdvancedAPI] ASAccount login"),o.login(e).then(e=>{t.invoke(Result.success(e))},e=>{t.invoke(Result.fail(e))})}function getUserInfo(...e){let t=e.pop();var e=e.pop(),o=requireAPI("ASAccount");console.debug("[AdvancedAPI] ASAccount getUserInfo"),o.getUserInfo(e).then(e=>{t.invoke(Result.success(e))},e=>{t.invoke(Result.fail(e))})}function chooseImage(...e){console.debug("[AdvancedAPI] start chooseImage");let t=e.pop();var o=requireAPI("ASImage"),e=e[0];o.chooseImage(e).then(e=>{t.invoke(Result.success(e))},e=>{t.invoke(Result.fail(e))})}function getImageInfo(...e){console.debug("[AdvancedAPI] start getImageInfo");let t=e.pop();var o=requireAPI("ASImage"),e=e[0];o.getImageInfo(e).then(e=>{t.invoke(Result.success(e))},e=>{t.invoke(Result.fail(e))})}function saveImageToPhotosAlbum(...e){console.debug("[AdvancedAPI] start saveImageToPhotosAlbum");let t=e.pop();var o=requireAPI("ASImage"),e=e[0];o.saveImageToPhotosAlbum(e).then(e=>{t.invoke(Result.success(e))},e=>{t.invoke(Result.fail(e))})}function compressImage(...e){console.debug("[AdvancedAPI] start compressImage");let t=e.pop();var o=requireAPI("ASImage"),e=e[0];o.compressImage(e).then(e=>{t.invoke(Result.success(e))},e=>{t.invoke(Result.fail(e))})}function setScreenBrightness(...e){let t=e.pop();e=e.pop(),requireAPI("ASBrightness").setScreenBrightness(e).then(e=>{t.invoke(Result.success(e))},e=>{t.invoke(Result.fail(e))})}function getScreenBrightness(...e){let t=e.pop();requireAPI("ASBrightness").getScreenBrightness().then(e=>{console.info("[AdvancedAPI] getScreenBrightness raw = "+e[0].value),e=e[0].value/255,console.info("[AdvancedAPI] getScreenBrightness = "+e),t.invoke(Result.success({value:e}))},e=>{t.invoke(Result.fail(e))})}function setKeepScreenOn(...e){let t=e.pop();e=e.pop(),requireAPI("ASBrightness").asSetKeepScreenOn(e).then(()=>{t.invoke(Result.success())},()=>{t.invoke(Result.fail())})}function saveFile(...e){let t=e.pop();e=e.pop()||{},requireAPI("ASFile").saveFile(e).then(e=>{t.invoke(Result.success(e))}).catch(e=>{t.invoke(Result.fail(e))})}function getSavedFileList(...e){let t=e.pop();requireAPI("ASFile").getSavedFileList().then(e=>{t.invoke(Result.success(e))}).catch(e=>{t.invoke(Result.fail(e))})}function getSavedFileInfo(...e){let t=e.pop();e=e.pop()||{},requireAPI("ASFile").getSavedFileInfo(e).then(e=>{t.invoke(Result.success(e))}).catch(e=>{t.invoke(Result.fail(e))})}function removeSavedFile(...e){let t=e.pop();e=e.pop()||{},requireAPI("ASFile").removeSavedFile(e).then(e=>{t.invoke(Result.success(e))}).catch(e=>{t.invoke(Result.fail(e))})}function getFileInfo(...e){let t=e.pop();e=e.pop()||{},requireAPI("ASFile").getFileInfo(e).then(e=>{t.invoke(Result.success(e))}).catch(e=>{t.invoke(Result.fail(e))})}function openDocument(...e){let t=e.pop();e=e.pop()||{},requireAPI("ASFile").openDocument(e).then(e=>{t.invoke(Result.success(e))}).catch(e=>{t.invoke(Result.fail(e))})}function getFileSystemManager(){return requireAPI("ASFile").getFileSystemManager()}function createInnerAudioContext(){return console.debug("[AdvancedAPI] start createInnerAudioContext"),requireAPI("ASAudio").createInnerAudioContext()}function saveVideoToPhotosAlbum(...e){console.debug("[AdvancedAPI] start saveVideoToPhotosAlbum");let t=e.pop();var o=requireAPI("ASVideo"),e=e[0];o.saveVideoToPhotosAlbum(e).then(e=>{t.invoke(Result.success(e))},e=>{t.invoke(Result.fail(e))})}function getVideoInfo(...e){console.debug("[AdvancedAPI] start getVideoInfo");let t=e.pop();var o=requireAPI("ASVideo"),e=e[0];o.getVideoInfo(e).then(e=>{t.invoke(Result.success(e))},e=>{t.invoke(Result.fail(e))})}function scanCode(...e){console.debug("[AdvancedAPI] start scanCode");let t=e.pop();e=e[0],requireAPI("ASScan").scanCode(e).then(e=>{t.invoke(Result.success(e))},e=>{t.invoke(Result.fail(e))})}let asInterfaceList={getSystemInfoSync:{method:getSystemInfoSync,needPromise:!1,needCallback:!1},getDeviceInfo:{method:getDeviceInfo,needPromise:!1},getWindowInfo:{method:getWindowInfo,needPromise:!1},getAppBaseInfo:{method:getAppBaseInfo,needPromise:!1},getAppAuthorizeSetting:{method:getAppAuthorizeSetting,needPromise:!1},getSystemSetting:{method:getSystemSetting,needPromise:!1},openAppAuthorizeSetting:{method:openAppAuthorizeSetting},getLocation:{method:getLocation},onLocationChange:{method:onLocationChange},offLocationChange:{method:offLocationChange,needPromise:!1},startLocationUpdate:{method:startLocationUpdate},startLocationUpdateBackground:{method:startLocationUpdateBackground},stopLocationUpdate:{method:stopLocationUpdate},onLocationChangeError:{method:onLocationChangeError},offLocationChangeError:{method:offLocationChangeError},makePhoneCall:{method:makePhoneCall},request:{method:request},uploadFile:{method:uploadFile},downloadFile:{method:downloadFile},navigateTo:{method:navigateTo},redirectTo:{method:redirectTo},navigateBack:{method:navigateBack},openBluetoothAdapter:{method:openBluetoothAdapter},startBluetoothDevicesDiscovery:{method:startBluetoothDevicesDiscovery},onBluetoothDeviceFound:{method:onBluetoothDeviceFound,needPromise:!1,needCallback:!1},offBluetoothDeviceFound:{method:offBluetoothDeviceFound,needPromise:!1,needCallback:!1},stopBluetoothDevicesDiscovery:{method:stopBluetoothDevicesDiscovery},onBluetoothAdapterStateChange:{method:onBluetoothAdapterStateChange,needPromise:!1,needCallback:!1},offBluetoothAdapterStateChange:{method:offBluetoothAdapterStateChange,needPromise:!1,needCallback:!1},getConnectedBluetoothDevices:{method:getConnectedBluetoothDevices},getBluetoothAdapterState:{method:getBluetoothAdapterState},closeBluetoothAdapter:{method:closeBluetoothAdapter},getBluetoothDevices:{method:getBluetoothDevices},setBLEMTU:{method:setBLEMTU},writeBLECharacteristicValue:{method:writeBLECharacteristicValue},readBLECharacteristicValue:{method:readBLECharacteristicValue},onBLEConnectionStateChange:{method:onBLEConnectionStateChange,needPromise:!1,needCallback:!1},offBLEConnectionStateChange:{method:offBLEConnectionStateChange,needPromise:!1,needCallback:!1},onBLECharacteristicValueChange:{method:onBLECharacteristicValueChange,needPromise:!1,needCallback:!1},offBLECharacteristicValueChange:{method:offBLECharacteristicValueChange,needPromise:!1,needCallback:!1},notifyBLECharacteristicValueChange:{method:notifyBLECharacteristicValueChange},getBLEDeviceServices:{method:getBLEDeviceServices},getBLEDeviceRSSI:{method:getBLEDeviceRSSI},getBLEDeviceCharacteristics:{method:getBLEDeviceCharacteristics},createBLEConnection:{method:createBLEConnection},closeBLEConnection:{method:closeBLEConnection},onAccelerometerChange:{method:onAccelerometerChange,needPromise:!1,needCallback:!1},offAccelerometerChange:{method:offAccelerometerChange,needPromise:!1,needCallback:!1},startAccelerometer:{method:startAccelerometer},stopAccelerometer:{method:stopAccelerometer},onCompassChange:{method:onCompassChange,needPromise:!1,needCallback:!1},offCompassChange:{method:offCompassChange,needPromise:!1,needCallback:!1},startCompass:{method:startCompass},stopCompass:{method:stopCompass},onGyroscopeChange:{method:onGyroscopeChange,needPromise:!1,needCallback:!1},startGyroscope:{method:startGyroscope},stopGyroscope:{method:stopGyroscope},startWifi:{method:startWifi},stopWifi:{method:stopWifi},getConnectedWifi:{method:getConnectedWifi},getWifiList:{method:getWifiList},onGetWifiList:{method:onGetWifiList,needPromise:!1,needCallback:!1},offGetWifiList:{method:offGetWifiList,needPromise:!1,needCallback:!1},connectWifi:{method:connectWifi},onWifiConnected:{method:onWifiConnected,needPromise:!1,needCallback:!1},offWifiConnected:{method:offWifiConnected,needPromise:!1,needCallback:!1},onWifiConnectedWithPartialInfo:{method:onWifiConnectedWithPartialInfo,needPromise:!1,needCallback:!1},offWifiConnectedWithPartialInfo:{method:offWifiConnectedWithPartialInfo,needPromise:!1,needCallback:!1},startSoterAuthentication:{method:startSoterAuthentication},checkIsSupportSoterAuthentication:{method:checkIsSupportSoterAuthentication},checkIsSoterEnrolledInDevice:{method:checkIsSoterEnrolledInDevice},addPhoneContact:{method:addPhoneContact},vibrate:{method:vibrate},vibrateLong:{method:vibrateLong},vibrateShort:{method:vibrateShort},onUserCaptureScreen:{method:onUserCaptureScreen,needPromise:!1,needCallback:!1},offUserCaptureScreen:{method:offUserCaptureScreen,needPromise:!1,needCallback:!1},hideKeyboard:{method:hideKeyboard},onKeyboardHeightChange:{method:onKeyboardHeightChange,needPromise:!1,needCallback:!1},offKeyboardHeightChange:{method:offKeyboardHeightChange,needPromise:!1,needCallback:!1},login:{method:login},getUserInfo:{method:getUserInfo},chooseImage:{method:chooseImage},getImageInfo:{method:getImageInfo},saveImageToPhotosAlbum:{method:saveImageToPhotosAlbum},compressImage:{method:compressImage},setScreenBrightness:{method:setScreenBrightness},getScreenBrightness:{method:getScreenBrightness},setKeepScreenOn:{method:setKeepScreenOn},saveFile:{method:saveFile},getSavedFileList:{method:getSavedFileList},getSavedFileInfo:{method:getSavedFileInfo},removeSavedFile:{method:removeSavedFile},getFileInfo:{method:getFileInfo},openDocument:{method:openDocument},getFileSystemManager:{method:getFileSystemManager,needPromise:!1,needCallback:!1},createInnerAudioContext:{method:createInnerAudioContext,needPromise:!1,needCallback:!1},saveVideoToPhotosAlbum:{method:saveVideoToPhotosAlbum},getVideoInfo:{method:getVideoInfo},scanCode:{method:scanCode}};function invokeModule(e,...t){console.debug("[AdvancedAPI] invokeModule moduleName = %s",e);var o=t.pop();if("number"==typeof o){let e=jsCallbackMap.get(o);e||(e=new JSCallback({id:o}),jsCallbackMap.set(o,e)),t.push(e)}else t.push(o);return o=asInterfaceList[e],triggerInterceptInvoke(e,t),triggerInterceptReturnValue(e,o=o.method.apply(null,t)),o}function triggerInterceptInvoke(e,t){var o=requireAPI("ASInterceptor");!1!==asInterfaceList[e].needCallback&&((t=[...t]).pop(),o.invoke(e,t))}function triggerInterceptReturnValue(e,t){requireAPI("ASInterceptor").returnValue(e,t)}function createAs(){let e={};return Object.keys(asInterfaceList).forEach(o=>{Object.defineProperty(e,o,{get:()=>(...e)=>{e=(t=interceptCallback(e,o,asInterfaceList[o].needPromise,asInterfaceList[o].needCallback)).args||[];var t=t.promise,e=invokeModule(o,...e);return t?t.promise:e}})}),e}let as=createAs(),AdvancedApi={init:function(e,t){var o;globalThis.as&&globalThis.requireAPI||(console.debug("[AdvancedAPI] init"),globalThis.as=as,globalThis.requireAPI=requireAPI$1,globalThis.isStageModel=!0,globalThis.abilityContext=e,media.createAVRecorder().then(e=>{globalThis.commonAvRecorder=e}),o=bundleManager.BundleFlag.GET_BUNDLE_INFO_WITH_SIGNATURE_INFO|bundleManager.BundleFlag.GET_BUNDLE_INFO_WITH_APPLICATION,globalThis.bundleInfoForSelf=bundleManager.getBundleInfoForSelfSync(o),globalThis.lastWindow=t,initContextOnStageModel(e))}};export default AdvancedApi;export{as,createAs}; diff --git a/ohos/AdvancedAPI_OHOS/project/advancedApiHsp/advanced_api_har/src/main/module.json5 b/ohos/AdvancedAPI_OHOS/project/advancedApiHsp/advanced_api_har/src/main/module.json5 new file mode 100644 index 0000000000..a480c86e62 --- /dev/null +++ b/ohos/AdvancedAPI_OHOS/project/advancedApiHsp/advanced_api_har/src/main/module.json5 @@ -0,0 +1,11 @@ +{ + "module": { + "name": "advanced_api_har", + "type": "har", + "deviceTypes": [ + "default", + "tablet", + "2in1" + ] + } +} diff --git a/ohos/AdvancedAPI_OHOS/project/advancedApiHsp/advanced_api_har/src/main/resources/base/element/string.json b/ohos/AdvancedAPI_OHOS/project/advancedApiHsp/advanced_api_har/src/main/resources/base/element/string.json new file mode 100644 index 0000000000..f51a9c8461 --- /dev/null +++ b/ohos/AdvancedAPI_OHOS/project/advancedApiHsp/advanced_api_har/src/main/resources/base/element/string.json @@ -0,0 +1,8 @@ +{ + "string": [ + { + "name": "page_show", + "value": "page from package" + } + ] +} diff --git a/ohos/AdvancedAPI_OHOS/project/advancedApiHsp/advanced_api_har/src/main/resources/en_US/element/string.json b/ohos/AdvancedAPI_OHOS/project/advancedApiHsp/advanced_api_har/src/main/resources/en_US/element/string.json new file mode 100644 index 0000000000..f51a9c8461 --- /dev/null +++ b/ohos/AdvancedAPI_OHOS/project/advancedApiHsp/advanced_api_har/src/main/resources/en_US/element/string.json @@ -0,0 +1,8 @@ +{ + "string": [ + { + "name": "page_show", + "value": "page from package" + } + ] +} diff --git a/ohos/AdvancedAPI_OHOS/project/advancedApiHsp/advanced_api_har/src/main/resources/zh_CN/element/string.json b/ohos/AdvancedAPI_OHOS/project/advancedApiHsp/advanced_api_har/src/main/resources/zh_CN/element/string.json new file mode 100644 index 0000000000..f51a9c8461 --- /dev/null +++ b/ohos/AdvancedAPI_OHOS/project/advancedApiHsp/advanced_api_har/src/main/resources/zh_CN/element/string.json @@ -0,0 +1,8 @@ +{ + "string": [ + { + "name": "page_show", + "value": "page from package" + } + ] +} diff --git a/ohos/AdvancedAPI_OHOS/project/advancedApiHsp/advanced_api_har/src/ohosTest/ets/test/Ability.test.ets b/ohos/AdvancedAPI_OHOS/project/advancedApiHsp/advanced_api_har/src/ohosTest/ets/test/Ability.test.ets new file mode 100644 index 0000000000..85c78f6757 --- /dev/null +++ b/ohos/AdvancedAPI_OHOS/project/advancedApiHsp/advanced_api_har/src/ohosTest/ets/test/Ability.test.ets @@ -0,0 +1,35 @@ +import { hilog } from '@kit.PerformanceAnalysisKit'; +import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium'; + +export default function abilityTest() { + describe('ActsAbilityTest', () => { + // Defines a test suite. Two parameters are supported: test suite name and test suite function. + beforeAll(() => { + // Presets an action, which is performed only once before all test cases of the test suite start. + // This API supports only one parameter: preset action function. + }) + beforeEach(() => { + // Presets an action, which is performed before each unit test case starts. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: preset action function. + }) + afterEach(() => { + // Presets a clear action, which is performed after each unit test case ends. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: clear action function. + }) + afterAll(() => { + // Presets a clear action, which is performed after all test cases of the test suite end. + // This API supports only one parameter: clear action function. + }) + it('assertContain', 0, () => { + // Defines a test case. This API supports three parameters: test case name, filter parameter, and test case function. + hilog.info(0x0000, 'testTag', '%{public}s', 'it begin'); + let a = 'abc'; + let b = 'b'; + // Defines a variety of assertion methods, which are used to declare expected boolean conditions. + expect(a).assertContain(b); + expect(a).assertEqual(a); + }) + }) +} \ No newline at end of file diff --git a/ohos/AdvancedAPI_OHOS/project/advancedApiHsp/advanced_api_har/src/ohosTest/ets/test/List.test.ets b/ohos/AdvancedAPI_OHOS/project/advancedApiHsp/advanced_api_har/src/ohosTest/ets/test/List.test.ets new file mode 100644 index 0000000000..794c7dc4ed --- /dev/null +++ b/ohos/AdvancedAPI_OHOS/project/advancedApiHsp/advanced_api_har/src/ohosTest/ets/test/List.test.ets @@ -0,0 +1,5 @@ +import abilityTest from './Ability.test'; + +export default function testsuite() { + abilityTest(); +} \ No newline at end of file diff --git a/ohos/AdvancedAPI_OHOS/project/advancedApiHsp/advanced_api_har/src/ohosTest/module.json5 b/ohos/AdvancedAPI_OHOS/project/advancedApiHsp/advanced_api_har/src/ohosTest/module.json5 new file mode 100644 index 0000000000..a0cfc76227 --- /dev/null +++ b/ohos/AdvancedAPI_OHOS/project/advancedApiHsp/advanced_api_har/src/ohosTest/module.json5 @@ -0,0 +1,13 @@ +{ + "module": { + "name": "advanced_api_har_test", + "type": "feature", + "deviceTypes": [ + "default", + "tablet", + "2in1" + ], + "deliveryWithInstall": true, + "installationFree": false + } +} diff --git a/ohos/AdvancedAPI_OHOS/project/advancedApiHsp/advanced_api_har/src/test/List.test.ets b/ohos/AdvancedAPI_OHOS/project/advancedApiHsp/advanced_api_har/src/test/List.test.ets new file mode 100644 index 0000000000..bb5b5c3731 --- /dev/null +++ b/ohos/AdvancedAPI_OHOS/project/advancedApiHsp/advanced_api_har/src/test/List.test.ets @@ -0,0 +1,5 @@ +import localUnitTest from './LocalUnit.test'; + +export default function testsuite() { + localUnitTest(); +} \ No newline at end of file diff --git a/ohos/AdvancedAPI_OHOS/project/advancedApiHsp/advanced_api_har/src/test/LocalUnit.test.ets b/ohos/AdvancedAPI_OHOS/project/advancedApiHsp/advanced_api_har/src/test/LocalUnit.test.ets new file mode 100644 index 0000000000..165fc1615e --- /dev/null +++ b/ohos/AdvancedAPI_OHOS/project/advancedApiHsp/advanced_api_har/src/test/LocalUnit.test.ets @@ -0,0 +1,33 @@ +import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium'; + +export default function localUnitTest() { + describe('localUnitTest', () => { + // Defines a test suite. Two parameters are supported: test suite name and test suite function. + beforeAll(() => { + // Presets an action, which is performed only once before all test cases of the test suite start. + // This API supports only one parameter: preset action function. + }); + beforeEach(() => { + // Presets an action, which is performed before each unit test case starts. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: preset action function. + }); + afterEach(() => { + // Presets a clear action, which is performed after each unit test case ends. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: clear action function. + }); + afterAll(() => { + // Presets a clear action, which is performed after all test cases of the test suite end. + // This API supports only one parameter: clear action function. + }); + it('assertContain', 0, () => { + // Defines a test case. This API supports three parameters: test case name, filter parameter, and test case function. + let a = 'abc'; + let b = 'b'; + // Defines a variety of assertion methods, which are used to declare expected boolean conditions. + expect(a).assertContain(b); + expect(a).assertEqual(a); + }); + }); +} \ No newline at end of file diff --git a/ohos/AdvancedAPI_OHOS/project/advancedApiHsp/advanced_api_hsp/.gitignore b/ohos/AdvancedAPI_OHOS/project/advancedApiHsp/advanced_api_hsp/.gitignore new file mode 100644 index 0000000000..e2713a2779 --- /dev/null +++ b/ohos/AdvancedAPI_OHOS/project/advancedApiHsp/advanced_api_hsp/.gitignore @@ -0,0 +1,6 @@ +/node_modules +/oh_modules +/.preview +/build +/.cxx +/.test \ No newline at end of file diff --git a/ohos/AdvancedAPI_OHOS/project/advancedApiHsp/advanced_api_hsp/Index.ets b/ohos/AdvancedAPI_OHOS/project/advancedApiHsp/advanced_api_hsp/Index.ets new file mode 100644 index 0000000000..8b8666f85f --- /dev/null +++ b/ohos/AdvancedAPI_OHOS/project/advancedApiHsp/advanced_api_hsp/Index.ets @@ -0,0 +1,2 @@ +import AdvancedAPI,{ as } from './src/main/ets/utils/advancedapi.min' +export { AdvancedAPI, as } \ No newline at end of file diff --git a/ohos/AdvancedAPI_OHOS/project/advancedApiHsp/advanced_api_hsp/build-profile.json5 b/ohos/AdvancedAPI_OHOS/project/advancedApiHsp/advanced_api_hsp/build-profile.json5 new file mode 100644 index 0000000000..ce80db2a16 --- /dev/null +++ b/ohos/AdvancedAPI_OHOS/project/advancedApiHsp/advanced_api_hsp/build-profile.json5 @@ -0,0 +1,28 @@ +{ + "apiType": "stageMode", + "buildOption": { + }, + "buildOptionSet": [ + { + "name": "release", + "arkOptions": { + "obfuscation": { + "ruleOptions": { + "enable": false, + "files": [ + "./obfuscation-rules.txt" + ] + } + } + }, + }, + ], + "targets": [ + { + "name": "default" + }, + { + "name": "ohosTest" + } + ] +} \ No newline at end of file diff --git a/ohos/AdvancedAPI_OHOS/project/advancedApiHsp/advanced_api_hsp/hvigorfile.ts b/ohos/AdvancedAPI_OHOS/project/advancedApiHsp/advanced_api_hsp/hvigorfile.ts new file mode 100644 index 0000000000..d993120bd7 --- /dev/null +++ b/ohos/AdvancedAPI_OHOS/project/advancedApiHsp/advanced_api_hsp/hvigorfile.ts @@ -0,0 +1,6 @@ +import { hspTasks } from '@ohos/hvigor-ohos-plugin'; + +export default { + system: hspTasks, /* Built-in plugin of Hvigor. It cannot be modified. */ + plugins:[] /* Custom plugin to extend the functionality of Hvigor. */ +} diff --git a/ohos/AdvancedAPI_OHOS/project/advancedApiHsp/advanced_api_hsp/obfuscation-rules.txt b/ohos/AdvancedAPI_OHOS/project/advancedApiHsp/advanced_api_hsp/obfuscation-rules.txt new file mode 100644 index 0000000000..272efb6ca3 --- /dev/null +++ b/ohos/AdvancedAPI_OHOS/project/advancedApiHsp/advanced_api_hsp/obfuscation-rules.txt @@ -0,0 +1,23 @@ +# Define project specific obfuscation rules here. +# You can include the obfuscation configuration files in the current module's build-profile.json5. +# +# For more details, see +# https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/source-obfuscation-V5 + +# Obfuscation options: +# -disable-obfuscation: disable all obfuscations +# -enable-property-obfuscation: obfuscate the property names +# -enable-toplevel-obfuscation: obfuscate the names in the global scope +# -compact: remove unnecessary blank spaces and all line feeds +# -remove-log: remove all console.* statements +# -print-namecache: print the name cache that contains the mapping from the old names to new names +# -apply-namecache: reuse the given cache file + +# Keep options: +# -keep-property-name: specifies property names that you want to keep +# -keep-global-name: specifies names that you want to keep in the global scope + +-enable-property-obfuscation +-enable-toplevel-obfuscation +-enable-filename-obfuscation +-enable-export-obfuscation \ No newline at end of file diff --git a/ohos/AdvancedAPI_OHOS/project/advancedApiHsp/advanced_api_hsp/oh-package.json5 b/ohos/AdvancedAPI_OHOS/project/advancedApiHsp/advanced_api_hsp/oh-package.json5 new file mode 100644 index 0000000000..d622e6b473 --- /dev/null +++ b/ohos/AdvancedAPI_OHOS/project/advancedApiHsp/advanced_api_hsp/oh-package.json5 @@ -0,0 +1,11 @@ +{ + "name": "advanced_api_hsp", + "version": "1.0.0", + "description": "Please describe the basic information.", + "main": "Index.ets", + "author": "", + "license": "Apache-2.0", + "packageType": "InterfaceHar", + "dependencies": { + } +} \ No newline at end of file diff --git a/ohos/AdvancedAPI_OHOS/project/advancedApiHsp/advanced_api_hsp/src/main/ets/pages/Index.ets b/ohos/AdvancedAPI_OHOS/project/advancedApiHsp/advanced_api_hsp/src/main/ets/pages/Index.ets new file mode 100644 index 0000000000..423b4276ec --- /dev/null +++ b/ohos/AdvancedAPI_OHOS/project/advancedApiHsp/advanced_api_hsp/src/main/ets/pages/Index.ets @@ -0,0 +1,17 @@ +@Entry +@Component +struct Index { + @State message: string = 'Hello World'; + + build() { + Row() { + Column() { + Text(this.message) + .fontSize(50) + .fontWeight(FontWeight.Bold) + } + .width('100%') + } + .height('100%') + } +} \ No newline at end of file diff --git a/ohos/AdvancedAPI_OHOS/project/advancedApiHsp/advanced_api_hsp/src/main/ets/utils/advancedapi.min.js b/ohos/AdvancedAPI_OHOS/project/advancedApiHsp/advanced_api_hsp/src/main/ets/utils/advancedapi.min.js new file mode 100644 index 0000000000..2d410ec514 --- /dev/null +++ b/ohos/AdvancedAPI_OHOS/project/advancedApiHsp/advanced_api_hsp/src/main/ets/utils/advancedapi.min.js @@ -0,0 +1,48 @@ +var global,_dec,_dec2,_dec3,_dec4,_dec5,_dec6,_dec7,_dec8,_dec9,_dec10,_dec11,_dec12,_dec13,_dec14,_class,_dec$1,_dec2$1,_class$1,_dec$2,_dec2$2,_dec3$1,_class$2;void 0===global&&(global=globalThis); +import abilityFeatureAbility from "@ohos.ability.featureAbility"; +import deviceInfo from "@ohos.deviceInfo"; +import display from "@ohos.display"; +import I18n from "@ohos.i18n"; +import abilityAccessCtrl from "@ohos.abilityAccessCtrl"; +import bluetooth from "@ohos.bluetooth"; +import geoLocationManager from "@ohos.geoLocationManager"; +import wifiManager from "@ohos.wifiManager"; +import window from "@ohos.window"; +import mapCommon from "@hms.core.map.mapCommon"; +import map from "@hms.core.map.map"; +import wantAgent from "@ohos.app.ability.wantAgent"; +import backgroundTaskManager from "@ohos.resourceschedule.backgroundTaskManager"; +import call from "@ohos.telephony.call"; +import http from "@ohos.net.http"; +import request$1 from "@ohos.request"; +import fs from "@ohos.file.fs"; +import photoAccessHelper from "@ohos.file.photoAccessHelper"; +import dataSharePredicates from "@ohos.data.dataSharePredicates"; +import bluetoothManager from "@ohos.bluetoothManager"; +import access from "@ohos.bluetooth.access"; +import ble from "@ohos.bluetooth.ble"; +import connection from "@ohos.bluetooth.connection"; +import promptAction from "@ohos.promptAction"; +import router from "@ohos.router"; +import wifi from "@ohos.wifi"; +import userIAM_userAuth from "@ohos.userIAM.userAuth"; +import prompt from "@ohos.prompt"; +import sensor from "@ohos.sensor"; +import contact from "@ohos.contact"; +import vibrator from "@ohos.vibrator"; +import inputMethod from "@ohos.inputMethod"; +import fileuri from "@ohos.file.fileuri"; +import wantConstant from "@ohos.ability.wantConstant"; +import bundleManager from "@ohos.bundle.bundleManager"; +import image from "@ohos.multimedia.image"; +import picker from "@ohos.file.picker"; +import media from "@ohos.multimedia.media"; +import audio from "@ohos.multimedia.audio"; +import avSession from "@ohos.multimedia.avsession"; +import cryptoFramework from "@ohos.security.cryptoFramework"; +import buffer from "@ohos.buffer"; +import util from "@ohos.util"; +import settings from "@ohos.settings"; +import scanCore from "@hms.core.scan.scanCore"; +import scanBarcode from "@hms.core.scan.scanBarcode"; +function _applyDecoratedDescriptor(o,a,e,t,r){var s={};return Object.keys(t).forEach(function(e){s[e]=t[e]}),s.enumerable=!!s.enumerable,s.configurable=!!s.configurable,("value"in s||s.initializer)&&(s.writable=!0),s=e.slice().reverse().reduce(function(e,t){return t(o,a,e)||e},s),r&&void 0!==s.initializer&&(s.value=s.initializer?s.initializer.call(r):void 0,s.initializer=void 0),void 0===s.initializer?(Object.defineProperty(o,a,s),null):s}function _defineProperty(e,t,o){return(t=_toPropertyKey(t))in e?Object.defineProperty(e,t,{value:o,enumerable:!0,configurable:!0,writable:!0}):e[t]=o,e}function _toPrimitive(e,t){if("object"!=typeof e||!e)return e;var o=e[Symbol.toPrimitive];if(void 0===o)return("string"===t?String:Number)(e);if("object"!=typeof(o=o.call(e,t||"default")))return o;throw new TypeError("@@toPrimitive must return a primitive value.")}function _toPropertyKey(e){return"symbol"==typeof(e=_toPrimitive(e,"string"))?e:e+""}let context=abilityFeatureAbility.getContext();function initContextOnStageModel(e){(context=e).startAbilityForResult||(context.startAbilityForResult=context.startAbility),context.getAbilityInfo=function(){return new Promise((e,t)=>{try{e(this.abilityInfo)}catch(e){t(e)}})},context.getFilesDir=function(){return new Promise((e,t)=>{try{e(this.filesDir)}catch(e){t(e)}})},context.getCacheDir=function(){return new Promise((e,t)=>{try{e(this.cacheDir)}catch(e){t(e)}})}}class AbilityBase{static getAbilityInfo(){return new Promise((t,o)=>{this.hasAbilityInfo?t(this.abilityInfo):context.getAbilityInfo().then(e=>{this.hasAbilityInfo=!0,this.abilityInfo=e,console.log("[QAFAPI] getAbilityInfo successful. "),t(e)}).catch(e=>{console.error("[QAFAPI] getAbilityInfo failed. Cause: "+JSON.stringify(e)),o(e)})})}}_defineProperty(AbilityBase,"abilityInfo",{}),_defineProperty(AbilityBase,"hasAbilityInfo",!1);class DeivceBase{static getDeviceInfo(){return deviceInfo}}class DisplayBase{static ohosGetDisplay(){let e=null;try{e=display.getDefaultDisplaySync()}catch(e){console.error("[QAFAPI] display error message: "+JSON.stringify(e))}return e}}class ASDevice{getSystemInfoSync(){var{brand:e,productModel:t,osFullName:o,deviceType:a,udid:r,sdkApiVersion:s}=DeivceBase.getDeviceInfo(),i=o.split("-")[0],n=i,c=o.split("-")[1],l=c,d=I18n.System.getSystemLanguage(),{rotation:h,densityPixels:u}=p=DisplayBase.ohosGetDisplay(),{width:p,height:f}=p,p=Math.round(p/u),f=Math.round(f/u),h=1===h||3===h?"landscape":"portrait",{signatureInfo:A,versionName:g,versionCode:m,appInfo:y}=globalThis.bundleInfoForSelf,y=context.resourceManager.getStringSync(y.labelId),A=A.appId,S=context.config.language,{width:v,height:C,top:P}=null==(v=globalThis.lastWindow.getWindowProperties())?void 0:v.windowRect,{isFullScreen:E,isLayoutFullScreen:b}=globalThis.lastWindow.getWindowProperties(),I=globalThis.lastWindow.getWindowAvoidArea(window.AvoidAreaType.TYPE_SYSTEM),I=Math.round(((null==I||null==(I=I.topRect)?void 0:I.height)||0)/u),E=E||b?Math.round(C/u):Math.round((C+I)/u),P=Math.round(P/u),b={deviceType:a,deviceBrand:e,brand:e,deviceModel:t,platform:n,model:t,deviceOrientation:h,devicePixelRatio:u,pixelRatio:u,system:o,osName:n,osVersion:l,version:l,osLanguage:d,language:d,ohosAPILevel:s,romName:i,romVersion:c,appId:A,appName:y,appVersion:g,appVersionCode:m,appLanguage:S,screenWidth:p,screenHeight:f,windowWidth:Math.round(v/u),windowHeight:Math.round(C/u),windowTop:P,windowBottom:E,statusBarHeight:I};return r&&(b.deviceId=r),b}getDeviceInfo(){console.debug("[AdvancedAPI] start ASDevice getDeviceInfo");var{brand:e,productModel:t,osFullName:o,deviceType:a,osFullName:r,udid:s}=DeivceBase.getDeviceInfo(),i=e,n=t,r=r.split("-")[0],{densityPixels:c,rotation:l}=DisplayBase.ohosGetDisplay(),r={platform:r,deviceBrand:i,deviceModel:t,deviceType:a,deviceOrientation:1===l||3===l?"landscape":"portrait",devicePixelRatio:c,system:o,brand:e,model:n};return s&&(r.deviceId=s),r}getWindowInfo(){console.debug("[AdvancedAPI] start ASDevice getWindowInfo");var e=(t=DisplayBase.ohosGetDisplay()).densityPixels,{width:t,height:o}=t,{width:a,height:r,top:s}=null==(a=globalThis.lastWindow.getWindowProperties())?void 0:a.windowRect,{isFullScreen:i,isLayoutFullScreen:n}=globalThis.lastWindow.getWindowProperties(),c=globalThis.lastWindow.getWindowAvoidArea(window.AvoidAreaType.TYPE_SYSTEM),c=Math.round(((null==c||null==(c=c.topRect)?void 0:c.height)||0)/e),i=i||n?Math.round(r/e):Math.round((r+c)/e),s=Math.round(s/e),a=Math.round(a/e),r=Math.round(r/e);return{pixelRatio:e,screenWidth:Math.round(t/e),screenHeight:Math.round(o/e),windowWidth:a,windowHeight:r,windowTop:s,windowBottom:i,statusBarHeight:c}}getAppBaseInfo(){console.debug("[AdvancedAPI] start ASDevice getAppBaseInfo");var{signatureInfo:e,versionName:t,versionCode:o,appInfo:a}=globalThis.bundleInfoForSelf,r=a.debug,a=context.resourceManager.getStringSync(a.labelId),e=e.appId,s=context.config.language,i=(Environment.envProp("colorMode",-1),AppStorage.get("colorMode"));return{appId:e,appName:a,appVersion:t,appVersionCode:o,appLanguage:s,enableDebug:r,theme:0===i?"light":1===i?"dark":"auto"}}getAppAuthorizeSetting(){console.debug("[AdvancedAPI] start ASDevice getAppAuthorizeSetting");var e=abilityAccessCtrl.createAtManager(),t=globalThis.bundleInfoForSelf.appInfo.accessTokenId,o=e=>-1===e?"denied":0===e?"authorized":"config error";let a="not determined";try{a=o(a=e.checkAccessTokenSync(t,"ohos.permission.WRITE_IMAGEVIDEO"))}catch(e){console.debug("[AdvancedAPI] ASDevice getAppAuthorizeSetting checkAccessToken album fail")}let r="not determined";try{r=o(r=e.checkAccessTokenSync(t,"ohos.permission.USE_BLUETOOTH"))}catch(e){console.debug("[AdvancedAPI] ASDevice getAppAuthorizeSetting checkAccessToken bluetooth fail")}let s="not determined";try{s=o(s=e.checkAccessTokenSync(t,"ohos.permission.CAMERA"))}catch(e){console.debug("[AdvancedAPI] ASDevice getAppAuthorizeSetting checkAccessToken camera fail")}let i="not determined";try{i=o(i=e.checkAccessTokenSync(t,"ohos.permission.LOCATION"))}catch(e){console.debug("[AdvancedAPI] ASDevice getAppAuthorizeSetting checkAccessToken location fail")}let n="not determined";try{n=0===e.checkAccessTokenSync(t,"ohos.permission.APPROXIMATELY_LOCATION")?"full":"reduced"}catch(e){console.debug("[AdvancedAPI] ASDevice getAppAuthorizeSetting checkAccessToken locationAccuracy fail")}let c="not determined";try{c=o(c=e.checkAccessTokenSync(t,"ohos.permission.MICROPHONE"))}catch(e){console.debug("[AdvancedAPI] ASDevice getAppAuthorizeSetting checkAccessToken microphone fail")}let l="not determined";try{l=o(l=e.checkAccessTokenSync(t,"ohos.permission.NOTIFICATION_CONTROLLER"))}catch(e){console.debug("[AdvancedAPI] ASDevice getAppAuthorizeSetting checkAccessToken notification fail")}let d="not determined";try{d=o(d=e.checkAccessTokenSync(t,"ohos.permission.READ_CALENDAR"))}catch(e){console.debug("[AdvancedAPI] ASDevice getAppAuthorizeSetting checkAccessToken phoneCalendar fail")}return{albumAuthorized:a,bluetoothAuthorized:r,cameraAuthorized:s,locationAuthorized:i,locationAccuracy:n,microphoneAuthorized:c,notificationAuthorized:l,phoneCalendarAuthorized:d}}getSystemSetting(){let e,t,o,a,r;try{e=!(2!==(e=bluetooth.getState())&&5!==e)}catch(e){console.error("errCode:"+e.code+",errMessage:"+e.message),a=e.message}try{t=geoLocationManager.isLocationEnabled()}catch(e){console.error("errCode:"+e.code+",errMessage:"+e.message),r=e.message}try{o=wifiManager.isWifiActive()}catch(e){console.error("errCode:"+e.code+",errMessage:"+e.message)}var s=DisplayBase.ohosGetDisplay().rotation;return{bluetoothEnabled:e,bluetoothError:a,locationEnabled:t,locationError:r,wifiEnabled:o,deviceOrientation:1===s||3===s?"landscape":"portrait"}}openAppAuthorizeSetting(){var e={bundleName:"com.huawei.hmos.settings",abilityName:"com.huawei.hmos.settings.MainAbility",uri:"application_info_entry",parameters:{pushParams:context.applicationInfo.name}};return context.startAbilityForResult(e)}}let ErrorCode$1={SHARE_INSTALLED_ERROR:-1001,SUCCESS:0,COMMON_ERROR:200,USER_REJECT:201,PARAMETER_ERROR:202,SERVICE_UNAVIALABLE:203,SERVICE_TIMEOUT:204,NOT_SUPPORT_SERVICE_COUNTRY:205,NOT_IN_WHITE_LIST:206,SYSTEM_PERMISSION_DENIAL:207,IO_ERROR:300,FILE_NOT_FOUND:301,FILE_EXIST:302,FILE_EXTENSION_NOT_EXIST:303,FILE_PATH_NOT_LEGAL:304,WEB_PAGE_NOT_FOUND:404,QUICKAPP_IN_BACKGROUND:500,LOCATION_SWITCH_CLOSED:1e3,PAY_CHECKKEY_FAIL:1001,SIM_NOT_FOUND:1001,SIGNIN_AUTH_FAIL:1002,OPERATORS_GET_FAIL:1002,ALARM_SYSTEM_ERROR:1003,AGD_COMMON_ERROR:2001,WIDGET_NOT_SUPPORT:2001,CARD_CALL_QUICK_APP_CENTER_FAIL:2003,BI_REPORT_ERROR:4001,PAY_CANCEL_CODE:3e4,PAY_CERTIFICATION_CODE:30102},BLHErrorCode={OK:0,OTHER_ERRORS:200,NOT_INIT:1e4,NOT_AVAILABLE:10001,NO_DEVICE:10002,CONNECTION_FAIL:10003,NO_SERVICE:10004,NO_CHARACTERISTIC:10005,NO_CONNECTION:10006,PROPERTY_NOT_SUPPORT:10007,SYSTEM_ERROR:10008,SYSTEM_NOT_SUPPORT:10009,LOCATION_NOT_TURN_ON:10010,NO_SUCH_INTERFACE:10100,DEVICE_DOES_NOT_EXIST:10101,NOT_AVAILABLE_TIRAMISU:10102},WifiErrorCode={PASSWORD_ERROR:1e3,CONNECTION_TIMEOUT:1001,DUPLICATE_REQUEST:1002,WIFI_NOT_TURNED_ON:1003,GPS_NOT_TURNED_ON:1004,INVALID_SSID:1005};function dataToArray(e){return Array.isArray(e)?e:[e]}class Result{static success(e,t=!1,o=!1){return{method:"success",arguments:dataToArray(e),ignoreComplete:t,ifKeepAlive:o}}static fail(e,t=!1,o=!1){return{method:"fail",arguments:dataToArray(e),ignoreComplete:t,ifKeepAlive:o}}static cancel(e,t=!1,o=!1){return{method:"cancel",arguments:dataToArray(e),ignoreComplete:t,ifKeepAlive:o}}static callback(e,t=!1,o=!1){return{method:"callback",arguments:dataToArray(e),ignoreComplete:t,ifKeepAlive:o}}static destroy(e,t=!1,o=!1){return{method:"destroy",arguments:dataToArray(e),ignoreComplete:t,ifKeepAlive:o}}}class ASLocation{constructor(){this.locationChangeCallbacks=[],this.locationChangeErrorCallback=(e,t)=>{},this.bothCallback=(t,e)=>{if(e)this.locationChangeErrorCallback({errMsg:e[2].arguments[0],errCode:e[2].arguments[1]});else for(let e=0;e{var o=t.authResults,a=t.dialogShownResults,r=o.length;for(let e=0;e{var e;return console.debug("[AdvancedAPI] current location: %s",JSON.stringify(t)),"gcj02"===(null==s?void 0:s.type)?(e={latitude:t.latitude,longitude:t.longitude},map.convertCoordinate(mapCommon.CoordinateType.WGS84,mapCommon.CoordinateType.GCJ02,e).then(e=>(t.latitude=e.latitude,t.longitude=e.longitude,Promise.resolve(t))).catch(e=>(console.debug("[AdvancedAPI] promise, convertCoordinate: error= %s",JSON.stringify(e)),Promise.reject([[e.message,ErrorCode$1.SERVICE_UNAVIALABLE]])))):Promise.resolve(t)}).catch(e=>(console.debug("[AdvancedAPI] promise, getCurrentLocation: error= %s",JSON.stringify(e)),Promise.reject([[e.message,ErrorCode$1.SERVICE_UNAVIALABLE]])))}catch(e){return console.error("[AdvancedAPI] errCode:"+e.code+",errMessage:"+e.message),Promise.reject([[e.message,ErrorCode$1.SERVICE_UNAVIALABLE]])}})}onLocationChange(e){console.debug("[AdvancedAPI] start ASLocation onLocationChange"),this.locationChangeCallbacks.push(e)}offLocationChange(e){console.debug("[AdvancedAPI] start ASLocation offLocationChange"),e?0<=(e=this.locationChangeCallbacks.indexOf(e))&&this.locationChangeCallbacks.splice(e,1):this.locationChangeCallbacks=[]}onLocationChangeError(e){console.debug("[AdvancedAPI] start ASLocation onLocationChangeError"),this.locationChangeErrorCallback=e}offLocationChangeError(){console.debug("[AdvancedAPI] start ASLocation offLocationChangeError"),this.locationChangeErrorCallback=(e,t)=>{}}startLocationUpdate(){console.debug("[AdvancedAPI] start ASLocation startLocationUpdate");var e=abilityAccessCtrl.createAtManager();try{return e.requestPermissionsFromUser(context,["ohos.permission.APPROXIMATELY_LOCATION","ohos.permission.LOCATION"]).then(t=>{var o=t.authResults,a=o.length;for(let e=0;e{var o=t.authResults,a=o.length;for(let e=0;e{e={wants:[{bundleName:e.bundleName,abilityName:e.name}],operationType:wantAgent.OperationType.START_ABILITY,requestCode:0,wantAgentFlags:[wantAgent.WantAgentFlags.UPDATE_PRESENT_FLAG]},wantAgent.getWantAgent(e).then(e=>backgroundTaskManager.startBackgroundRunning(context,backgroundTaskManager.BackgroundMode.LOCATION,e)).then(()=>{console.debug("[AdvancedAPI] start bg operation succeeded")}).catch(e=>{console.error("[AdvancedAPI] start bg operation failed Cause: "+e)})});try{return geoLocationManager.on("locationChange",{priority:515,scenario:768,timeInterval:0,distanceInterval:0,maxAccuracy:0},this.bothCallback),Promise.resolve("SUCCESS")}catch(e){return Promise.reject([[e.message,e.code]])}})}catch(e){return Promise.reject([["startLocationUpdateBackground failed",ErrorCode$1.COMMON_ERROR]])}}stopLocationUpdate(e){console.debug("[AdvancedAPI] start ASLocation stopLocationUpdate"),backgroundTaskManager.stopBackgroundRunning(context).then(()=>{console.debug("[AdvancedAPI] stop operation succeeded")}).catch(e=>{console.error("[AdvancedAPI] stop operation fail cause: "+JSON.stringify(e))});try{return geoLocationManager.off("locationChange"),Promise.resolve("SUCCESS")}catch(e){return Promise.reject([["stopLocationUpdate failed",ErrorCode$1.COMMON_ERROR]])}}}class ASPhone{makePhoneCall(e){return e&&e.phoneNumber&&"string"==typeof e.phoneNumber&&""!==e?call.makeCall(e.phoneNumber):new Promise((e,t)=>{t(["param is invalid.",ErrorCode$1.PARAMETER_ERROR])})}}function isMac(e){return/^[A-Fa-f\d]{2}:[A-Fa-f\d]{2}:[A-Fa-f\d]{2}:[A-Fa-f\d]{2}:[A-Fa-f\d]{2}:[A-Fa-f\d]{2}$/.test(e)}function isUuid(e){return/^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$/.test(e)}function isLower(e){return e===e.toLowerCase()}function isNumber(e){return"number"==typeof e&&!Number.isNaN(e)&&Number.isFinite(e)}function isString(e){return"string"==typeof e}function isBoolean(e){return"boolean"==typeof e}function isFunction(e){return"function"==typeof e}function isArrayBuffer(e){return"[object ArrayBuffer]"===Object.prototype.toString.call(e)}function isNull(e){return null===e}function isUndefined(e){return void 0===e}function isArray(e){return Array.isArray(e)}function isHexcolor(e){return/^#[0-9a-fA-F]{6}$/i.test(e)||/^#[0-9a-fA-F]{3}$/i.test(e)}function checkDataType(t,e,o,a){let r=!1;try{if(e&&(isNull(t)||isUndefined(t)))throw new Error("The param data is required");if(!isString(o)&&!isArray(o))throw new Error("The param dataType should be a String or an Array");if(!isNull(a)&&!isUndefined(a)&&!isFunction(a))throw new Error("If customCheck exist,it should be a Function");if(!e&&(isNull(t)||isUndefined(t)))return!0;isString(o)?r=checkSingleDataType(t,o):isArray(o)&&(r=o.some(e=>checkSingleDataType(t,e))),r&&isFunction(a)&&(r=a(t))}catch(e){return console.log(e),!1}return r}function checkSingleDataType(e,t){let o=!1;switch(t){case"string":o=isString(e);break;case"number":o=isNumber(e);break;case"boolean":o=isBoolean(e);break;case"function":o=isFunction(e);break;case"arraybuffer":o=isArrayBuffer(e);break;case"array":o=isArray(e);break;case"hexcolor":o=isHexcolor(e);break;case"null":o=isNull(e);break;case"undefined":o=isUndefined(e);break;default:throw new Error("The param dataType is unsupport")}return o}class MediaLibraryBase{static getPermissions(){try{let e=["ohos.permission.SHORT_TERM_WRITE_IMAGEVIDEO"],t=abilityAccessCtrl.createAtManager();return new Promise(o=>{t.requestPermissionsFromUser(context,e).then(e=>{var t=e.authResults[0],e=e.dialogShownResults[0];o({perNum:t,dialogShownResults:e})})})}catch(e){console.error("[AdvancedAPI] getPermissions is fail!",JSON.stringify(e))}}static getMediaType(e){return photoAccessHelper.PhotoType[e]}static getFileKey(){return photoAccessHelper.PhotoKeys}static getMedia(){return photoAccessHelper.getPhotoAccessHelper(context)}static async createAsset(e,t,o){var a=o.split(".").pop().toString(),o=o.split(".").shift().toString();return e.createAsset(t,a,{title:o})}static closeAsset(e,o){return new Promise(t=>{e.close(o,e=>{t(void 0===e)})})}static getFd(e){return new Promise(t=>{e.open("rw").then(e=>{t(e)}).catch(()=>{t(!1)})})}}function switchInternalToHapSandBox(e){return e.startsWith("internal://bundle/")?e.replace("internal://bundle",context.bundleCodeDir):e.startsWith("internal://cache/")?e.replace("internal://cache",context.cacheDir):e.startsWith("internal://files/")?e.replace("internal://files",context.filesDir):e.startsWith("internal://preferences/")?e.replace("internal://preferences",context.preferencesDir):e.startsWith("internal://temp/")?e.replace("internal://temp",context.tempDir):e.startsWith("internal://database/")?e.replace("internal://database",context.databaseDir):e.startsWith("internal://distributedFiles/")?e.replace("internal://distributedFiles",context.distributedFilesDir):e}function switchHapSandBoxToInternal(e){return e.startsWith(context.bundleCodeDir)?e.replace(context.bundleCodeDir,"internal://bundle"):e.startsWith(context.cacheDir)?e.replace(context.cacheDir,"internal://cache"):e.startsWith(context.filesDir)?e.replace(context.filesDir,"internal://files"):e.startsWith(context.preferencesDir)?e.replace(context.preferencesDir,"internal://preferences"):e.startsWith(context.tempDir)?e.replace(context.tempDir,"internal://temp"):e.startsWith(context.databaseDir)?e.replace(context.databaseDir,"internal://database"):e.startsWith(context.distributedFilesDir)?e.replace(context.distributedFilesDir,"internal://distributedFiles"):e}function isFileUri(e){return e&&"string"==typeof e&&(e.startsWith("file://")||e.startsWith("datashare://"))}function isSandboxPath(e){return e&&"string"==typeof e&&(e.startsWith("/data/storage/")||e.startsWith("internal://"))}function getFdFromUriOrSandBoxPath(t){try{return fs.openSync(t,fs.OpenMode.READ_ONLY).fd}catch(e){console.info(`[AdvancedAPI] Can not get file from uri: ${t} `)}throw new Error("file is not exist")}async function getFileAssetFromUri(e){try{-1===(await MediaLibraryBase.getPermissions()).perNum&&console.debug("[AdvancedAPI] permission fail");var t=photoAccessHelper.getPhotoAccessHelper(context),o=new dataSharePredicates.DataSharePredicates,a=(console.debug(`[AdvancedAPI] getFileAssetFromUri uri: ${e} `),o.equalTo(photoAccessHelper.PhotoKeys.URI,e.toString()),{fetchColumns:[photoAccessHelper.PhotoKeys.URI,photoAccessHelper.PhotoKeys.PHOTO_TYPE,photoAccessHelper.PhotoKeys.SIZE,photoAccessHelper.PhotoKeys.DURATION,photoAccessHelper.PhotoKeys.WIDTH,photoAccessHelper.PhotoKeys.HEIGHT,photoAccessHelper.PhotoKeys.TITLE,photoAccessHelper.PhotoKeys.ORIENTATION],predicates:o}),r=await t.getAssets(a),s=(console.debug(`[AdvancedAPI] getFileAssetFromUri fetchResult: ${JSON.stringify(r)} `),await r.getFirstObject());return console.debug(`[AdvancedAPI] getFileAssetFromUri asset: ${JSON.stringify(s)} `),r.close(),s}catch(e){console.debug("[AdvancedAPI] getAsset is fail!,"+e)}}function pathToCache(e){try{var t=switchInternalToHapSandBox(e),o=t.slice(t.lastIndexOf("/")),a=context.cacheDir+o;return fs.copyFile(t,a,e=>{e&&console.info("[AdvancedAPI] Failed to copy: "+JSON.stringify(e))}),switchHapSandBoxToInternal(a)}catch(e){console.error("[AdvancedAPI] to copy: "+JSON.stringify(e))}}async function saveMedia(e,t,o,a){try{var r=photoAccessHelper.getPhotoAccessHelper(context),s=t.split(".").pop().toString(),i=[{title:t.split(".").shift().toString().toString(),fileNameExtension:s.toString(),photoType:e}],n=[o.toString()],c=(await r.showAssetsCreationDialog(n,i))[0],l=fs.openSync(c,fs.OpenMode.READ_WRITE);return await fs.write(l.fd,a),fs.closeSync(l),c}catch(e){console.error("[AdvancedAPI] saveMedia is fail!: "+JSON.stringify(e))}}function arrayBufferToBase64(e){return requireAPI("ASBuffer").arrayBufferToBase64(e)}let errMsgMap=new Map([[401,"Parameter error"],[201,"Permission denied"],[2300003,"URL using bad/illegal format or missing URL"],[2300006,"Could not resolve host name"],[2300007,"Couldn not connect to server"],[2300009,"Access denied to remote resource"],[2300023,"Failed writing received data to disk/application"],[2300025,"Upload failed"],[2300026,"Failed to open/read local data from file/application"],[2300028,"Timeout was reached"],[2300073,"Remote file already exists"],[2300078,"Remote file not found"],[2300999,"Unknown Other Error"]]);class ASRequest{request(e){return console.debug("[AdvancedAPI] ASRequest request"),new RequestTask(e)}uploadFile(e){return console.debug("[AdvancedAPI] ASRequest uploadFile : %s",JSON.stringify(e)),new UploadTask(e)}downloadFile(e){return console.debug("[AdvancedAPI] ASRequest downloadFile %s",JSON.stringify(e)),new DownloadTask(e)}}class RequestTask{constructor(s){let{url:i,header:a,method:n="GET",timeout:c,responseType:l,enableCache:d}=s||{},h=(s||{}).data,{success:u,fail:p,complete:f}=s||{};if(this.abortFlag=!1,this.fail=p,this.complete=f,this.httpRequest=http.createHttp(),this.headersCallback=new Map,s){let e=!1;for(var A in a)if("content-type"===A.toLowerCase()){a[A].toLowerCase().includes("application/x-www-form-urlencoded")&&(e=!0);break}if(h&&(e||["GET","OPTIONS","DELETE","TRACE","CONNECT"].includes(n))){var g,m=[];for(g in h)m.push(encodeURIComponent(g)+"="+encodeURIComponent(h[g]));h=m.join("&")}if(a)for(var y in a)a[y]=""+a[y];let t={method:n,extraData:h||{},header:a,expectDataType:l&&"arraybuffer"===l?http.HttpDataType.ARRAY_BUFFER:http.HttpDataType.STRING,usingCache:d||!1},o=!1,r=setTimeout(()=>{var e;console.error("[AdvancedAPI] request error: Timeout was reached"),o=!0,p&&!this.abortFlag&&(this.result=e={errMsg:"Timeout was reached"},p(e)),f&&!this.abortFlag&&f(this.result),this.httpRequest&&(this.httpRequest.destroy(),this.httpRequest=void 0)},c||6e4);this.httpRequest.request("string"==typeof i?i:"",t).then(a=>{if(clearTimeout(r),console.debug("[AdvancedAPI] request url %s success",i),u&&!this.abortFlag){let e=a.result,t=!1,o=(s||{}).responseType;if(o&&"json"!==o)"[object ArrayBuffer]"===Object.prototype.toString.call(e)&&(e=arrayBufferToBase64(e),t=!0);else if("string"==typeof a.result)try{e=JSON.parse(e)}catch(e){}o={isArrayBuffer:!1,data:e,statusCode:a.responseCode,header:a.header,cookies:"string"==typeof a.cookies?a.cookies?[a.cookies]:[]:a.cookies,errMsg:"request:ok"},t&&(o.isArrayBuffer=!0),this.result=o,u(o)}}).catch(e=>{clearTimeout(r),o||(console.error("[AdvancedAPI] request error: "+JSON.stringify(e)),p&&!this.abortFlag&&(e={errMsg:errMsgMap.has(e.code)?errMsgMap.get(e.code):"Unknown Error"},this.result=e,p(e)))}).finally(()=>{o||(f&&!this.abortFlag&&f(this.result),this.httpRequest&&(this.httpRequest.destroy(),this.httpRequest=void 0))})}else console.error("[AdvancedAPI] request error: params illegal")}abort(){console.debug("[AdvancedAPI] request abort"),this.abortFlag=!0,this.httpRequest&&(this.httpRequest.destroy(),this.httpRequest=void 0,this.res={errMsg:"request:fail abort"},this.fail&&this.fail(this.res),this.complete)&&this.complete(this.res)}onHeadersReceived(t){var e=e=>{this.abortFlag||t({header:e})};t?this.headersCallback.has(t)||(this.headersCallback.set(t,e),this.httpRequest&&this.httpRequest.on("headersReceive",e)):console.error("[AdvancedAPI] Invalid, callback is null")}offHeadersReceived(e){e?this.headersCallback.has(e)?(this.httpRequest&&this.httpRequest.off("headersReceive",this.headersCallback.get(e)),this.headersCallback.delete(e)):console.debug("[AdvancedAPI] offHeadersReceived callback invalid"):(this.headersCallback.clear(),this.httpRequest&&this.httpRequest.off("headersReceive"))}}class UploadTask{constructor(e){var{url:t,files:o,filePath:a,name:r,header:s,formData:i}=e||{};let{success:n,fail:c,complete:l}=e||{},d=(e=a.startsWith("internal://cache/")?a:pathToCache(a),this.progressCallback=new Map,this.headersCallback=new Map,[]);o?o.forEach(function(e){var t,o;"string"==typeof e.uri&&(t=e.uri.substring(e.uri.lastIndexOf("/")+1),o=e.uri.substring(e.uri.lastIndexOf(".")+1),d.push({filename:t,name:e.name,uri:e.uri,type:o}))}):"string"==typeof e&&(a=e.substring(e.lastIndexOf("/")+1),o=e.substring(e.lastIndexOf(".")+1),d.push({filename:a,name:r,uri:e,type:o}));var h,u,p=[];for([h,u]of Object.entries(i||{}))p.push({name:h,value:"string"==typeof u?u:JSON.stringify(u)});a={url:t,header:s||{},method:"POST",files:d,data:p},this.successHandle=e=>{n&&n(e),l&&l(e)},this.failHandle=e=>{c&&c(e),l&&l(e)};try{console.debug("[AdvancedAPI] request upload"),request$1.uploadFile(globalThis.abilityContext,a).then(e=>{if(this.uploadTask=e,this.abortFlag&&(this.abortFlag=!1,this.uploadTask.delete(()=>{this.res={errMsg:"uploadFile:fail abort"},this.failHandle(this.res)})),this.progressFlag){this.progressFlag=!1;for(var t of this.progressCallback.values())this.uploadTask.on("progress",t)}if(this.headersFlag){this.headersFlag=!1;for(var o of this.headersCallback.values())this.uploadTask.on("headerReceive",o)}this.uploadTask.on("headerReceive",this.headersReceivedHandle.bind(this)),this.uploadTask.on("complete",()=>{var e;console.debug("[AdvancedAPI] upload success"),this.res={data:(null==(e=this.receivedData)?void 0:e.body)||{},header:(null==(e=this.receivedData)?void 0:e.headers)||{},cookies:[],statusCode:200,errMsg:"uploadFile:ok"},this.successHandle(this.res)}),this.uploadTask.on("fail",()=>{console.debug("[AdvancedAPI] upload fail"),this.res={errMsg:"uploadFile:fail"},this.failHandle(this.res)})}).catch(e=>{console.error("[AdvancedAPI] upload request error: "+e.message),this.res={errMsg:"uploadFile:fail "+e.message},this.failHandle(this.res)})}catch(e){console.error("[AdvancedAPI] upload request err.code : "+e.code+", err.message : "+e.message),this.res={errMsg:"uploaddFile:fail "+e.message},this.failHandle(this.res)}}abort(){this.res={errMsg:"uploadFile:fail abort"},this.uploadTask?this.uploadTask.delete(()=>{this.failHandle(this.res)}):this.abortFlag=!0}onProgressUpdate(o){function e(e,t){o({progress:Math.ceil(100*e/t),totalBytesSent:e,totalBytesExpectedToSend:t})}o?this.progressCallback.has(o)||(this.progressCallback.set(o,e),this.uploadTask?this.uploadTask.on("progress",e):this.progressFlag=!0):console.error("[AdvancedAPI] Invalid, callback is null")}offProgressUpdate(e){e?this.progressCallback.has(e)?(this.uploadTask&&this.uploadTask.off("progress",this.progressCallback.get(e)),this.progressCallback.delete(e)):console.debug("[AdvancedAPI] offProgressUpdate callback invalid"):(this.progressCallback.clear(),this.uploadTask&&this.uploadTask.off("progress"))}headersReceivedHandle(e){this.receivedData=e}onHeadersReceived(t){var e=e=>{this.abortFlag||t({header:e.headers||{}})};t?this.headersCallback.has(t)||(this.headersCallback.set(t,e),this.uploadTask?this.uploadTask.on("headerReceive",e):this.headersFlag=!0):console.error("[AdvancedAPI] Invalid, callback is null")}offHeadersReceived(e){e?this.headersCallback.has(e)?(this.uploadTask&&this.uploadTask.off("headerReceive",this.headersCallback.get(e)),this.headersCallback.delete(e)):console.debug("[AdvancedAPI] offHeadersReceived callback invalid"):(this.headersCallback.clear(),this.uploadTask&&(this.uploadTask.off("headerReceive"),this.uploadTask.on("headerReceive",this.headersReceivedHandle.bind(this))))}}class DownloadTask{constructor(e){let{url:t,header:o,filePath:a}=e||{},{success:r,fail:s,complete:i}=e||{},n=(this.progressCallback=new Map,"string"==typeof t&&(e=(new Date).getTime(),this.filename="Download_"+e+"_"+t.substring(t.lastIndexOf("/")+1).replace(/[^a-zA-Z0-9.]/,"").slice(-16)),a||"internal://cache/"+this.filename);e=switchInternalToHapSandBox(n),e={url:this.isEncodeUri(t)?t:encodeURI(t),header:o||{},filePath:e},this.successHandle=e=>{r&&r(e),i&&i(e)},this.failHandle=e=>{s&&s(e),i&&i(e)};try{console.debug("[AdvancedAPI] request download"),request$1.downloadFile(globalThis.abilityContext,e).then(e=>{if(this.downloadTask=e,this.abortFlag&&(this.abortFlag=!1,this.downloadTask.delete(()=>{console.debug("[AdvancedAPI] download fail"),this.res={errMsg:"downloadFile:fail abort"},this.failHandle(this.res)})),this.progressFlag){this.progressFlag=!1;for(var t of this.progressCallback.values())this.downloadTask.on("progress",t)}this.downloadTask.on("complete",()=>{console.debug("[AdvancedAPI] download success"),this.res={tempFilePath:n,statusCode:200,errMsg:"downloadFile:ok"},a&&Object.assign(this.res,{filePath:a}),this.downloadTask.getTaskInfo().then(e=>{console.debug("[AdvancedAPI] download info: %s",JSON.stringify(e)),e.downloadTotalBytes&&Object.assign(this.res,{dataLength:e.downloadTotalBytes})}).catch(e=>{console.error("[AdvancedAPI] download request get task info error: "+e.message)}).finally(()=>{this.successHandle(this.res)})}),this.downloadTask.on("fail",()=>{console.debug("[AdvancedAPI] download fail"),this.res={errMsg:"downloadFile:fail"},this.failHandle(this.res)})}).catch(e=>{console.error("[AdvancedAPI] download request error: "+e.message),this.res={errMsg:"downloadFile:fail "+e.message},this.failHandle(this.res)})}catch(e){console.error("[AdvancedAPI] download request err.code : "+e.code+", err.message : "+e.message),this.res={errMsg:"downloadFile:fail "+e.message},this.failHandle(this.res)}}abort(){this.downloadTask?this.downloadTask.delete(()=>{console.debug("[AdvancedAPI] download fail"),this.res={errMsg:"downloadFile:fail abort"},this.failHandle(this.res)}):this.abortFlag=!0}onProgressUpdate(o){function e(e,t){o({progress:Math.ceil(100*e/t),totalBytesWritten:e,totalBytesExpectedToWrite:t})}o?this.progressCallback.has(o)||(this.progressCallback.set(o,e),this.downloadTask?this.downloadTask.on("progress",e):this.progressFlag=!0):console.error("[AdvancedAPI] Invalid, callback is null")}offProgressUpdate(e){e?this.progressCallback.has(e)?this.downloadTask&&(this.downloadTask.off("progress",this.progressCallback.get(e)),this.progressCallback.delete(e)):console.debug("[AdvancedAPI] offProgressUpdate callback invalid"):(this.progressCallback.clear(),this.downloadTask&&this.downloadTask.off("progress"))}onHeadersReceived(e){console.debug("[AdvancedAPI] onHeadersReceived not support")}offHeadersReceived(e){console.debug("[AdvancedAPI] offHeadersReceived not support")}isEncodeUri(e){return!e||/^[a-zA-Z0-9-_.!~*'();/?:@&=+$,#]+$/.test(e)}}let SCAN_MODE={LIMITED:5,DURATION:0};class BluetoothBase{static getPermissions(){let t=["ohos.permission.ACCESS_BLUETOOTH"],o=abilityAccessCtrl.createAtManager();return new Promise(async e=>{0===(await o.requestPermissionsFromUser(context,t)).authResults[0]?e(!0):e(!1)})}static onStateChange(e){try{return access.on("stateChange",e)}catch(e){console.warn("[AdvancedAPI] on bondStateChange fail")}}static on(e){try{return connection.on("bluetoothDeviceFind",e)}catch(e){console.warn("[AdvancedAPI] on fail")}}static onBLE(e){try{ble.on("BLEDeviceFind",e)}catch(e){console.warn("[AdvancedAPI] BLE.on.BLEDeviceFind fail")}}static createGattClientDevice(e){try{return ble.createGattClientDevice(e)}catch(e){console.warn("[AdvancedAPI] createGattClientDevice fail")}}static enableBluetooth(){try{return access.enableBluetooth()}catch(e){console.warn("[AdvancedAPI] enableBluetooth fail")}}static disableBluetooth(){try{return access.disableBluetooth()}catch(e){console.warn("[AdvancedAPI] disableBluetooth fail")}}static bluetoothState(){try{return access.getState()}catch(e){console.error("[AdvancedAPI] getState fail, errCode: "+e.code+", errMessage: "+e.message)}}static startBluetoothDiscovery(){connection.setBluetoothScanMode(connection.ScanMode.SCAN_MODE_LIMITED_DISCOVERABLE,SCAN_MODE.DURATION);try{return connection.startBluetoothDiscovery()}catch(e){console.warn("[AdvancedAPI] startBluetoothDiscovery fail")}}static off(){try{return connection.off("bluetoothDeviceFind")}catch(e){console.warn("[AdvancedAPI] off fail")}}static getRemoteDeviceName(e){try{return connection.getRemoteDeviceName(e)}catch(e){console.warn("[AdvancedAPI] getRemoteDeviceName fail")}}static stopBluetoothDiscovery(){try{return connection.stopBluetoothDiscovery()}catch(e){console.warn("[AdvancedAPI] no need to stop")}}static startBLEScan(e){try{ble.startBLEScan(null,{interval:e,dutyMode:ble.ScanDuty.SCAN_MODE_LOW_POWER,matchMode:ble.MatchMode.MATCH_MODE_AGGRESSIVE})}catch(e){console.error("[QAFAPI] startBLEScan errCode:"+e.code+",errMessage:"+e.message)}}static stopBLEScan(){try{ble.stopBLEScan()}catch(e){console.error("[QAFAPI] stopBLEScan errCode:"+e.code+",errMessage:"+e.message)}}static offBLE(){try{ble.off("BLEDeviceFind")}catch(e){console.warn("[AdvancedAPI] BLE.off.BLEDeviceFind fail")}}static getProfile(e){try{return bluetoothManager.getProfileInstance(e).getConnectionDevices()}catch(e){console.warn("[AdvancedAPI] getProfileInstance fail")}}static getConnectedBLEDevices(){try{return ble.getConnectedBLEDevices()}catch(e){console.error("[AdvancedAPI]getConnectedBLEDevices errCode:"+e.code+",errMessage:"+e.message)}}}function jsMethod(s){return(e,t,o)=>{var a=s&&s.common?e.constructor._jsBaseMethods=e.constructor._jsBaseMethods||{}:e.constructor._jsMethods=e.constructor._jsMethods||{},e=void 0!==(s=void 0!==s?s:{}).alias?s.alias:t,r=void 0===s.callback||s.callback;a[e]={methodName:t,callback:r}}}class PromptBase{static showToast(o){return new Promise((e,t)=>{promptAction.showToast(o),e()})}static showDialog(o,a){return new Promise((e,t)=>{promptAction.showDialog(o,a)})}static showActionMenu(o,a){return new Promise((e,t)=>{promptAction.showActionMenu(o,a)})}static ohosShowDialog(e){return promptAction.showDialog(e)}}let BLESTATE={STATE_ON:2,STATE_OFF:0,INDEX:1,STATE_CONNECTED:2,STATE_DISCONNECTED:0},DEFAULT={OPEN:!1,OPEN_MSG:"快应用加载器想要开启蓝牙",CLOSE_MSG:"快应用加载器请求关闭蓝牙",ALLOW_BUTTON:"允许",REFUSE_BUTTON:"拒绝"},BluetoothBaseModule=(_dec=jsMethod({alias:"openAdapter",common:!1,callback:!0}),_dec2=jsMethod({alias:"closeAdapter",common:!1,callback:!0}),_dec3=jsMethod({alias:"getAdapterState",common:!1,callback:!0}),_dec4=jsMethod({alias:"startDevicesDiscovery",common:!1,callback:!0}),_dec5=jsMethod({alias:"stopDevicesDiscovery",common:!1,callback:!0}),_dec6=jsMethod({alias:"getDevices",common:!1,callback:!0}),_dec7=jsMethod({alias:"getConnectedDevices",common:!1,callback:!0}),_dec8=jsMethod({alias:"createBLEConnection",common:!1,callback:!0}),_dec9=jsMethod({alias:"closeBLEConnection",common:!1,callback:!0}),_dec10=jsMethod({alias:"getBLEDeviceServices",common:!1,callback:!0}),_dec11=jsMethod({alias:"getBLEDeviceCharacteristics",common:!1,callback:!0}),_dec12=jsMethod({alias:"readBLECharacteristicValue",common:!1,callback:!0}),_dec13=jsMethod({alias:"writeBLECharacteristicValue",common:!1,callback:!0}),_dec14=jsMethod({alias:"notifyBLECharacteristicValueChange",common:!1,callback:!0}),_applyDecoratedDescriptor((_class=class{constructor(){_defineProperty(this,"BLECharacteristicCallback",e=>{console.debug("[AdvancedAPI] characteristicChange triger valueChange:"+JSON.stringify(e));var t,{serviceUuid:o,characteristicUuid:a}=e,e=new Uint8Array(e.characteristicValue),r={deviceId:this.deviceIdBle,serviceId:o,characteristicId:a,value:e};for(t of this.BLECharacteristicListeners)t(r)}),this.onadapterstatechange,this.ondevicefound,this.allowDuplicatesKey=!1,this.interval=0,this.state={available:BluetoothBase.bluetoothState()===BLESTATE.STATE_ON,discovering:!1},this.deviceIdBle,this.scanResult=[],this.gattClient=null,this.isOnBle={mode:!1},this.stateBLE={},this.services=[],this.bleCharacteristic={},this.characteristicValue=null,this.isInit=!1,this.devicesFoundListeners=[],this.adapterStateChangeListeners=[],this.BLEConnectionStateListeners=[],this.BLECharacteristicListeners=[]}openAdapter(e){let{operateAdapter:a=DEFAULT.OPEN}=e||{},r=BluetoothBase.bluetoothState()===BLESTATE.STATE_ON;return new Promise((t,o)=>{r?t([["bluetooth is turned"]]):a?this.promptTemp(DEFAULT.OPEN_MSG).then(e=>{e.index===BLESTATE.INDEX?(BluetoothBase.enableBluetooth()&&t([[BLHErrorCode.OK]]),this.state.available=!0):o([["user reject",BLHErrorCode.SYSTEM_ERROR]])}):o([["not available",BLHErrorCode.NOT_AVAILABLE]])})}closeAdapter(e){let{operateAdapter:o=DEFAULT.OPEN}=e||{},a=BluetoothBase.bluetoothState()===BLESTATE.STATE_OFF;return new Promise((t,e)=>{a?e([["bluetooth is not turned",BLHErrorCode.NOT_INIT]]):o?this.promptTemp(DEFAULT.CLOSE_MSG).then(e=>{if(e.index===BLESTATE.INDEX){BluetoothBase.disableBluetooth()&&t([[BLHErrorCode.OK]]),this.state.available=!1;try{BluetoothBase.offBLE()}catch(e){console.error("[QAFAPI] OpenHarmony Error ondevicefound,error Message:"+e)}}}):t([["closeBluetoothAdapter success"]])})}getAdapterState(){let t=BluetoothBase.bluetoothState()===BLESTATE.STATE_ON;return new Promise(e=>{e({discovering:this.state.discovering,available:t})})}startDevicesDiscovery(i){let t=BluetoothBase.bluetoothState()===BLESTATE.STATE_ON;return new Promise((e,o)=>{if(t){if(i){var{services:a,allowDuplicatesKey:r,interval:s}=i;if(a&&!isArray(a)||r&&!isBoolean(r)||s&&!isNumber(s))return void o([["invalidParam",BLHErrorCode.SYSTEM_ERROR]]);let t=[];if(a){if(!a.every(e=>(t.push({serviceUuid:e}),isUuid(e.toLowerCase()))))return void o([["uuid invalid",BLHErrorCode.NO_DEVICE]]);this.isOnBle.mode=!0}else t=null;r&&(this.allowDuplicatesKey=r),s&&(this.interval=s)}BluetoothBase.startBLEScan(this.interval),BluetoothBase.startBluetoothDiscovery()?(this.state.discovering=!0,e("ok")):o([["[QAFAPI] openHarmony startBluetoothDiscovery fail",BLHErrorCode.CONNECTION_FAIL]])}else o([["bluetooth is not turned",BLHErrorCode.NOT_AVAILABLE]])})}stopDevicesDiscovery(){return new Promise((e,t)=>{var o;BluetoothBase.bluetoothState()?(BluetoothBase.stopBLEScan(),o=BluetoothBase.stopBluetoothDiscovery(),this.state.discovering=!1,o?(e("ok"),this.devicesFoundListeners=[],this.isOnBle.mode=!1,this.interval=0,this.allowDuplicatesKey=!1):e("ok")):t(["bluetooth is not turned",BLHErrorCode.NOT_AVAILABLE])})}getDevices(){let o=BluetoothBase.bluetoothState()===BLESTATE.STATE_ON;return new Promise((e,t)=>{o?e([[{devices:this.scanResult}]]):t([["bluetooth is not turned",BLHErrorCode.NOT_AVAILABLE]])})}saveDevice(e){!this.allowDuplicatesKey&&this.isRepeat(this.scanResult,e.deviceId)||this.scanResult.push(e)}onFoundEvent(e){let a=this.getTemp();if(e[0]&&e[0].deviceId){var{deviceId:t,rssi:o,data:r}=e[0];a.deviceId=t,a.RSSI=o,a.serviceData=r;try{let o=BluetoothBase.createGattClientDevice(t);o.connect(),o.getDeviceName((e,t)=>{a.name=t,a.localName=t;try{o.disconnect(),o.close()}catch(e){console.warn("[QAFAPI] close client fail: "+JSON.stringify(e))}this.saveDevice(a)})}catch(e){console.warn("[QAFAPI] close client fail: "+JSON.stringify(e))}}else a.deviceId=e[0],a.name=BluetoothBase.getRemoteDeviceName(a.deviceId),a.localName=a.name,console.debug("[QAFAPI] onFoundEvent:"+JSON.stringify(a)),this.saveDevice(a)}getConnectedDevices(a){return new Promise((e,t)=>{if(BluetoothBase.bluetoothState()===BLESTATE.STATE_ON)if(a&&a.services&&isArray(a.services)&&0!==a.services.length){console.debug("[QAFAPI] services : "+JSON.stringify(a.services));var o=a.services.every(e=>isUuid(e.toLowerCase()))||!1;if(a&&o){let o=[];try{o=BluetoothBase.getConnectedBLEDevices()}catch(e){console.error("[QAFAPI] errCode:"+e.code+",errMessage:"+e.message)}console.debug("[QAFAPI] BleDeviceIds = "+JSON.stringify(o));try{[1,4,6,7].forEach(e=>{e=BluetoothBase.getProfile(e),console.error("[QAFAPI] profiles"+JSON.stringify(e)),e&&(o=[...o,...e])})}catch(e){console.error("[QAFAPI] getProfile fail"+e)}if((o=o.reduce((e,t)=>e.includes(t)?e:[...e,t],[]))&&0!==o.length){let t=[];o.forEach(e=>{t.push({name:BluetoothBase.getRemoteDeviceName(e),deviceId:e})}),e([[{devices:t}]])}else t([["no device",BLHErrorCode.NO_DEVICE]])}else console.debug("[QAFAPI] invalidParam services "),t([["invalidParam",BLHErrorCode.SYSTEM_ERROR]])}else t([["invalidParam",BLHErrorCode.SYSTEM_ERROR]]);else t([["bluetooth is not turned",BLHErrorCode.NOT_AVAILABLE]])})}createBLEConnection(e){let{deviceId:a,timeout:r}=e||{};return new Promise((t,o)=>{if(BluetoothBase.bluetoothState()===BLESTATE.STATE_ON)if(r&&!isNumber(r))o([["invalidParam",BLHErrorCode.SYSTEM_ERROR]]);else if(a&&isString(a)){this.gattClient=BluetoothBase.createGattClientDevice(a),this.gattClient.on("BLEConnectionStateChange",e=>{var t=2===e.state;this.stateBLE[e.deviceId]!==t&&(this.stateBLE[e.deviceId]=t)});try{this.gattClient.on("BLECharacteristicChange",this.BLECharacteristicCallback),console.debug("[AdvancedAPI] BLECharacteristicChange Registration succeeded.")}catch(e){console.error("AdvancedAPI BLECharacteristicChange Registration fail "+e.message)}let e=this.gattClient.connect();r?setTimeout(()=>{e?(t("ok"),this.deviceIdBle=a):o([["connection timed out",BLHErrorCode.CONNECTION_FAIL]])},r):e?(t("ok"),this.deviceIdBle=a):o([["fail connection",BLHErrorCode.CONNECTION_FAIL]])}else o([["invalidParam",BLHErrorCode.SYSTEM_ERROR]]);else o([["bluetooth is not turned",BLHErrorCode.NOT_AVAILABLE]])})}closeBLEConnection(e){let o=(e||{}).deviceId;return new Promise((e,t)=>{if(o&&isString(o))try{this.gattClient.disconnect(),this.gattClient.close(),this.gattClient=null,this.stateBLE[o]=!1,e("ok")}catch(e){t([["Failed to disconnect the Bluetooth connection",BLHErrorCode.SYSTEM_ERROR]])}else t([["Deviceid must be written",BLHErrorCode.SYSTEM_ERROR]])})}getBLEDeviceServices(e){let o=(e||{}).deviceId;return new Promise((t,e)=>{if(o&&isString(o))if(isMac(o))if(BluetoothBase.bluetoothState()===BLESTATE.STATE_ON){console.debug("[QAFAPI] getServices deviceId:"+o+" this.deviceIdBLE = "+this.deviceIdBle);let e;this.gattClient&&o===this.deviceIdBle?(console.debug("[QAFAPI] getServices deviceId:"+o),e=this.gattClient):((e=BluetoothBase.createGattClientDevice(o)).connect(),this.gattClient=e,this.deviceIdBle=o),e.getServices().then(e=>{let o=[];e.forEach(e=>{console.debug("[QAFAPI] getServices services = "+JSON.stringify(e));var{serviceUuid:e,isPrimary:t}=e,e={uuid:e,isPrimary:t};o.push(e)}),this.services=e,t([[{services:o}]])}).catch(e=>{console.error("[QAFAPI] getServices fail:"+JSON.stringify(e)),t([[{services:[]}]])})}else e([["bluetooth is not turned",BLHErrorCode.NOT_AVAILABLE]]);else e([["deviceId is not MAC",BLHErrorCode.SYSTEM_ERROR]]);else e([["invalidParam",BLHErrorCode.SYSTEM_ERROR]])})}getBLEDeviceCharacteristics(e){return new Promise((r,s)=>{if(e){let{deviceId:t,serviceId:a}=e;if(console.info("[QAFAPI] getBLEDeviceCharacteristics deviceId:"+t+" serviceId = "+a),t&&isString(t)&&a&&isString(a)){console.info("[QAFAPI] getBLEDeviceCharacteristics deviceId:"+t+" this.deviceIdBLE = "+this.deviceIdBle);let e;this.gattClient&&t===this.deviceIdBle?(console.info("[QAFAPI] getBLEDeviceCharacteristics deviceId:"+t),e=this.gattClient):((e=BluetoothBase.createGattClientDevice(t)).connect(),this.gattClient=e,this.deviceIdBle=t),e.getServices().then(e=>{let o;if(this.services.forEach(e=>{console.info("[QAFAPI] serviceId = "+JSON.stringify(e)),e.serviceUuid===a&&(o=e)}),o){let t=[];(this.bleDescriptor=o).characteristics.forEach(e=>{console.info("[QAFAPI] Servicesfound item = "+JSON.stringify(e)),t.push({uuid:e.characteristicUuid,properties:e.properties})}),r([[{characteristics:t}]])}else s([["Service not found",BLHErrorCode.NO_SERVICE]])}).catch(e=>{console.error("[QAFAPI] OpenHarmony Error getServices value,error Message:"+e),s([["property not support",BLHErrorCode.PROPERTY_NOT_SUPPORT]])})}else s([["invalidParam",BLHErrorCode.SYSTEM_ERROR]])}else s([["invalidParam",BLHErrorCode.SYSTEM_ERROR]])})}readBLECharacteristicValue(e){return new Promise((i,n)=>{if(e){let{deviceId:a,serviceId:r,characteristicId:s}=e;isString(a)&&isString(r)&&isString(s)&&a&&r&&isUuid(r.toLowerCase())&&s&&isUuid(s.toLowerCase())?isMac(a.toLowerCase())?this.queryBLECharacteristic(a,r).then(e=>{var t=[],e={serviceUuid:r.toLowerCase(),characteristicUuid:s.toLowerCase(),descriptorUuid:e.descriptorUuid,descriptorValue:e.descriptorValue},e=(t.push(e),{serviceUuid:r.toLowerCase(),characteristicUuid:s.toLowerCase(),characteristicValue:this.characteristicValue,descriptors:t}),t=(console.debug("[QAFAPI] characteristicIn = "+JSON.stringify(e)),null);let o;if(this.gattClient&&this.deviceIdBle===a)try{o=this.gattClient.readCharacteristicValue(e)}catch(e){n([[e.message,ErrorCode$1.PARAMETER_ERROR]]),console.error("[QAFAPI]readBLECharacteristicValue errCode:"+e.code+",errMessage:"+e.message)}else try{t=BluetoothBase.createGattClientDevice(a),o=t.readCharacteristicValue(e)}catch(e){n([[e.message,ErrorCode$1.PARAMETER_ERROR]]),console.error("[QAFAPI]readBLECharacteristicValue errCode:"+e.code+",errMessage:"+e.message)}o?o.then(e=>{i([e])}).catch(e=>{console.error("[AdvancedAPI] Failed to read characteristic value"+e.message),n([["property not support",BLHErrorCode.PROPERTY_NOT_SUPPORT]])}):n([["property not support",BLHErrorCode.PROPERTY_NOT_SUPPORT]])}).catch(e=>{n([["Bluetooth not available",BLHErrorCode.SYSTEM_ERROR]])}):n([["deviceId is not MAC",BLHErrorCode.SYSTEM_ERROR]]):n([["invalidParam",BLHErrorCode.SYSTEM_ERROR]])}else n([["invalidParam",BLHErrorCode.SYSTEM_ERROR]])})}writeBLECharacteristicValue(e){return new Promise((n,c)=>{if(e){let{deviceId:a,serviceId:r,characteristicId:s,value:i}=e;isString(a)&&isString(r)&&isString(s)&&isArrayBuffer(i)&&isMac(a)&&a&&r&&isUuid(r.toLowerCase())&&s&&isUuid(s.toLowerCase())&&isLower(s.toLowerCase())&&i?this.queryBLECharacteristic(a,r).then(e=>{var t=[],e={serviceUuid:r.toLowerCase(),characteristicUuid:s.toLowerCase(),descriptorUuid:e.descriptorUuid,descriptorValue:e.descriptorValue},e=(t.push(e),{serviceUuid:r.toLowerCase(),characteristicUuid:s.toLowerCase(),characteristicValue:i,descriptors:t}),t=(console.debug("[QAFAPI] characteristicIn = "+JSON.stringify(e)),null);let o;if(this.gattClient&&this.deviceIdBle===a)try{o=this.gattClient.writeCharacteristicValue(e)}catch(e){c([[e.message,ErrorCode$1.PARAMETER_ERROR]]),console.error("[QAFAPI]writeCharacteristicValue errCode:"+e.code+",errMessage:"+e.message)}else try{t=BluetoothBase.createGattClientDevice(a),o=t.writeCharacteristicValue(e)}catch(e){c([[e.message,ErrorCode$1.PARAMETER_ERROR]]),console.error("[QAFAPI]readBLECharacteristicValue errCode:"+e.code+",errMessage:"+e.message)}o?n("ok"):c([["property not support",BLHErrorCode.PROPERTY_NOT_SUPPORT]])}).catch(e=>{c([["Bluetooth not available",BLHErrorCode.SYSTEM_ERROR]])}):c([["invalidParam",BLHErrorCode.SYSTEM_ERROR]])}else c([["invalidParam",BLHErrorCode.SYSTEM_ERROR]])})}queryBLECharacteristic(t,r){return new Promise((o,a)=>{if(this.descriptors&&t.toLowerCase()===this.deviceIdBle.toLowerCase())o(this.descriptors);else{let e;this.gattClient&&t.toLowerCase()===this.deviceIdBle.toLowerCase()?(console.info("[QAFAPI] queryBLECharacteristic deviceId:"+t),e=this.gattClient):((e=BluetoothBase.createGattClientDevice(t)).connect(),this.gattClient=e,this.deviceIdBle=t),e.getServices().then(e=>{let t;e.forEach(e=>{e.serviceUuid.toLowerCase()===r.toLowerCase()&&(t=e)}),t?t.characteristics.forEach(e=>{e.serviceUuid.toLowerCase()===r.toLowerCase()?(this.characteristicValue=e.characteristicValue,e.descriptors.forEach(e=>{e.serviceUuid.toLowerCase()===r.toLowerCase()?(this.descriptors=e,console.info("[QAFAPI] Servicesfound descriptor = "+JSON.stringify(e)),o(this.descriptors)):a([["characteristics not found",BLHErrorCode.NO_SERVICE]])})):(console.error("[AdvancedAPI] characteristics not found"),a([["characteristics not found",BLHErrorCode.NO_SERVICE]]))}):a([["Service not found",BLHErrorCode.NO_SERVICE]])}).catch(e=>{console.error("[AdvancedAPI] getServices fail:"+e.message),a([["Service not found",BLHErrorCode.NO_SERVICE]])})}})}notifyBLECharacteristicValueChange(e){return new Promise((n,c)=>{if(e){let{deviceId:a,serviceId:r,characteristicId:s,state:i}=e;a&&isString(a)&&r&&isString(r)&&isUuid(r.toLowerCase())&&s&&isString(s)&&isUuid(s.toLowerCase())&&i&&isBoolean(i)?isMac(a.toLowerCase())?this.queryBLECharacteristic(a,r).then(e=>{console.debug("[QAFAPI] desc = "+JSON.stringify(e));var t=[],e={serviceUuid:r.toLowerCase(),characteristicUuid:s.toLowerCase(),descriptorUuid:e.descriptorUuid,descriptorValue:e.descriptorValue},e=(t.push(e),{serviceUuid:r.toLowerCase(),characteristicUuid:s.toLowerCase(),characteristicValue:this.characteristicValue,descriptors:t}),t=(console.debug("[QAFAPI] BLECharacteristic = "+JSON.stringify(e)),null);let o;if(this.gattClient&&this.deviceIdBle===a)try{o=this.gattClient.setNotifyCharacteristicChanged(e,i)}catch(e){return c([[e.message,ErrorCode$1.PARAMETER_ERROR]]),void console.error("[QAFAPI]setNotifyCharacteristicChanged errCode:"+e.code+",errMessage:"+e.message)}else try{t=BluetoothBase.createGattClientDevice(a),o=t.setNotifyCharacteristicChanged(e,i)}catch(e){return c([[e.message,ErrorCode$1.PARAMETER_ERROR]]),void console.error("[QAFAPI]setNotifyCharacteristicChanged errCode:"+e.code+",errMessage:"+e.message)}o?(console.debug("[QAFAPI] notify success"),n("ok")):c([["property not support",BLHErrorCode.PROPERTY_NOT_SUPPORT]])}):c([["deviceId is not MAC",BLHErrorCode.SYSTEM_ERROR]]):c([["invalidParam",BLHErrorCode.SYSTEM_ERROR]])}else c([["invalidParam",BLHErrorCode.SYSTEM_ERROR]])})}getBLEDeviceRSSI(a){return new Promise((t,o)=>{if(this.gattClient&&this.deviceIdBle===a)this.gattClient.getRssiValue().then(e=>{t(e)}).catch(e=>{o(e.message)});else try{var e=BluetoothBase.createGattClientDevice(a);e.connect(),this.gattClient=e,this.deviceIdBle=a,e.getRssiValue().then(e=>{t(e)}).catch(e=>{o(e.message)})}catch(e){o(e.message)}})}getTemp(){return{RSSI:"",localName:"",advertisData:"",advertisServiceUUIDs:"",name:"",serviceData:"",deviceId:""}}isRepeat(e,t){return e.some(e=>e.deviceId===t)}promptTemp(e){return PromptBase.ohosShowDialog({message:e,buttons:[{text:DEFAULT.REFUSE_BUTTON,color:"#1358e7"},{text:DEFAULT.ALLOW_BUTTON,color:"#1358e7"}]})}}).prototype,"openAdapter",[_dec],Object.getOwnPropertyDescriptor(_class.prototype,"openAdapter"),_class.prototype),_applyDecoratedDescriptor(_class.prototype,"closeAdapter",[_dec2],Object.getOwnPropertyDescriptor(_class.prototype,"closeAdapter"),_class.prototype),_applyDecoratedDescriptor(_class.prototype,"getAdapterState",[_dec3],Object.getOwnPropertyDescriptor(_class.prototype,"getAdapterState"),_class.prototype),_applyDecoratedDescriptor(_class.prototype,"startDevicesDiscovery",[_dec4],Object.getOwnPropertyDescriptor(_class.prototype,"startDevicesDiscovery"),_class.prototype),_applyDecoratedDescriptor(_class.prototype,"stopDevicesDiscovery",[_dec5],Object.getOwnPropertyDescriptor(_class.prototype,"stopDevicesDiscovery"),_class.prototype),_applyDecoratedDescriptor(_class.prototype,"getDevices",[_dec6],Object.getOwnPropertyDescriptor(_class.prototype,"getDevices"),_class.prototype),_applyDecoratedDescriptor(_class.prototype,"getConnectedDevices",[_dec7],Object.getOwnPropertyDescriptor(_class.prototype,"getConnectedDevices"),_class.prototype),_applyDecoratedDescriptor(_class.prototype,"createBLEConnection",[_dec8],Object.getOwnPropertyDescriptor(_class.prototype,"createBLEConnection"),_class.prototype),_applyDecoratedDescriptor(_class.prototype,"closeBLEConnection",[_dec9],Object.getOwnPropertyDescriptor(_class.prototype,"closeBLEConnection"),_class.prototype),_applyDecoratedDescriptor(_class.prototype,"getBLEDeviceServices",[_dec10],Object.getOwnPropertyDescriptor(_class.prototype,"getBLEDeviceServices"),_class.prototype),_applyDecoratedDescriptor(_class.prototype,"getBLEDeviceCharacteristics",[_dec11],Object.getOwnPropertyDescriptor(_class.prototype,"getBLEDeviceCharacteristics"),_class.prototype),_applyDecoratedDescriptor(_class.prototype,"readBLECharacteristicValue",[_dec12],Object.getOwnPropertyDescriptor(_class.prototype,"readBLECharacteristicValue"),_class.prototype),_applyDecoratedDescriptor(_class.prototype,"writeBLECharacteristicValue",[_dec13],Object.getOwnPropertyDescriptor(_class.prototype,"writeBLECharacteristicValue"),_class.prototype),_applyDecoratedDescriptor(_class.prototype,"notifyBLECharacteristicValueChange",[_dec14],Object.getOwnPropertyDescriptor(_class.prototype,"notifyBLECharacteristicValueChange"),_class.prototype),_class);class ASBluetooth extends BluetoothBaseModule{constructor(){super(),this.deviceFoundCallback=void 0,this.adapterStateCallback=void 0,this.BLEConnectionStateCallback=void 0,this.initBluetoothDeviceFound(),this.initBluetoothAdapterStateChange(),this.initBLEConnectionStateChange()}openBluetoothAdapter(){return new Promise(async(e,t)=>{if(!await BluetoothBase.getPermissions())return t(["permission fail",ErrorCode.USER_REJECT]);BluetoothBase.bluetoothState()===BLESTATE.STATE_ON?(this.isInit=!0,e("ok")):t([["not available",BLHErrorCode.NOT_AVAILABLE]])})}closeBluetoothAdapter(){let o=BluetoothBase.bluetoothState()===BLESTATE.STATE_OFF;return new Promise((e,t)=>{if(o)t([["bluetooth is not turned",BLHErrorCode.NOT_AVAILABLE]]);else{if(this.isInit=!1,BluetoothBase.stopBluetoothDiscovery(),this.state.discovering=!1,this.deviceIdBle="",this.scanResult=[],this.gattClient)try{this.gattClient.disconnect(),this.gattClient.close(),this.gattClient=null}catch(e){}this.isOnBle={mode:!1},this.stateBLE={},this.services=[],this.bleCharacteristic={},this.characteristicValue=null,this.devicesFoundListeners=[],this.adapterStateChangeListeners=[],this.BLEConnectionStateListeners=[],this.BLECharacteristicListeners=[],e("ok")}})}startBluetoothDevicesDiscovery(e){return this.isInit?this.startDevicesDiscovery(e):new Promise((e,t)=>{console.warn("[AdvancedAPI] bluetooth is no init"),t([["not init",BLHErrorCode.NOT_INIT]])})}stopBluetoothDevicesDiscovery(e){return this.isInit?this.stopDevicesDiscovery(e):new Promise((e,t)=>{console.warn("[AdvancedAPI] bluetooth is no init"),t([["not init",BLHErrorCode.NOT_INIT]])})}initBluetoothDeviceFound(){this.deviceFoundCallback=e=>{this.onFoundEvent(e);for(let e of this.devicesFoundListeners)setTimeout(()=>{e([this.scanResult])},this.interval)};try{BluetoothBase.on(this.deviceFoundCallback),BluetoothBase.onBLE(this.deviceFoundCallback)}catch(e){console.error("[AdvancedAPI] openHarmony ondevicefound fail "+e)}}onBluetoothDeviceFound(e){this.devicesFoundListeners.push(e)}offBluetoothDeviceFound(e){void 0===e?this.devicesFoundListeners.splice(0):"function"!=typeof e?console.error("[AdvancedAPI] offBluetoothAdapterStateChange, param is invalid:"+typeof e):-1<(e=this.devicesFoundListeners.indexOf(e))&&this.devicesFoundListeners.splice(e,1)}initBluetoothAdapterStateChange(){this.adapterStateCallback=e=>{var t=this.state.available;if(2===e?this.state.available=!0:0===e&&(this.state.available=!1),t!==this.state.available)for(var o of this.adapterStateChangeListeners)o(t)};try{BluetoothBase.onStateChange(e=>{this.adapterStateCallback(e)})}catch(e){console.error("[AdvancedAPI] onBluetoothAdapterStateChange errCode:"+e.code+",errMessage:"+e.message)}}onBluetoothAdapterStateChange(e){this.adapterStateChangeListeners.push(e)}offBluetoothAdapterStateChange(e){void 0===e?this.devicesFoundListeners.splice(0):"function"!=typeof e?console.error("[AdvancedAPI] offBluetoothAdapterStateChange, param is invalid:"):-1<(e=this.adapterStateChangeListeners.indexOf(e))&&this.adapterStateChangeListeners.splice(e,1)}getConnectedBluetoothDevices(e){return this.isInit?this.getConnectedDevices(e):new Promise((e,t)=>{console.warn("[AdvancedAPI] bluetooth is no init"),t([["not init",BLHErrorCode.NOT_INIT]])})}getBluetoothDevices(){return this.isInit?this.getDevices():new Promise((e,t)=>{console.warn("[AdvancedAPI] bluetooth is no init"),t([["not init",BLHErrorCode.NOT_INIT]])})}getBluetoothAdapterState(){return this.isInit?this.getAdapterState():new Promise((e,t)=>{console.warn("[AdvancedAPI] bluetooth is no init"),t([["not init",BLHErrorCode.NOT_INIT]])})}asSetBLEMTU(a){return new Promise((t,o)=>{if(a&&a.deviceId&&a.mtu)if(isString(a.deviceId)&&isNumber(a.mtu))try{console.debug("[AdvancedAPI] asSetBLEMTU deviceId:"+a.deviceId+" this.deviceIdBLE = "+this.deviceIdBle);let e;this.gattClient&&a.deviceId.toLowerCase()===this.deviceIdBle.toLowerCase()?(console.debug("[AdvancedAPI] asSetBLEMTU deviceId:"+a.deviceId),e=this.gattClient):((e=BluetoothBase.createGattClientDevice(a.deviceId)).connect(),this.gattClient=e,this.deviceIdBle=a.deviceId),this.gattClient.setBLEMtuSize(a.mtu),t("ok")}catch(e){console.error("[AdvancedAPI] setBLEMtuSize fail, errCode:"+e.code+",errMessage:"+e.message),o([[e.message,BLHErrorCode.SYSTEM_ERROR]])}else console.error("[AdvancedAPI] setBLEMTU fail, params error"),o([["param error",BLHErrorCode.SYSTEM_ERROR]]);else console.error("[AdvancedAPI] setBLEMTU fail, params error"),o([["param error",BLHErrorCode.SYSTEM_ERROR]])})}asWriteBLECharacteristicValue(e){return this.writeBLECharacteristicValue(e)}asReadBLECharacteristicValue(e){return this.readBLECharacteristicValue(e)}initBLEConnectionStateChange(){this.BLEConnectionStateCallback=t=>{this.BLEConnectionStateListeners.forEach(e=>{e(t)})},this.stateBLE=new Proxy({},{get:(e,t)=>e[t],set:(e,t,o)=>(e={deviceId:t,connected:e[t]=o},console.debug("AdvancedAPI bleConnectionStateChange"),this.BLEConnectionStateCallback(e),!0)})}asOnBLEConnectionStateChange(e){this.BLEConnectionStateListeners.push(e)}asOffBLEConnectionStateChange(e){void 0===e?this.BLEConnectionStateListeners.splice(0):"function"!=typeof e?console.error("[AdvancedAPI] offBLEConnectionStateChange, param is invalid:"):-1<(e=this.BLEConnectionStateListeners.indexOf(e))&&this.BLEConnectionStateListeners.splice(e,1)}asOnBLECharacteristicValueChange(e){this.BLECharacteristicListeners.push(e)}asOffBLECharacteristicValueChange(e){void 0===e?this.BLECharacteristicListeners.splice(0):"function"!=typeof e?console.error("[AdvancedAPI] offBLECharacteristicValueChange, param is invalid:"):-1<(e=this.BLECharacteristicListeners.indexOf(e))&&this.BLECharacteristicListeners.splice(e,1)}asNotifyBLECharacteristicValueChange(e){return console.debug("[AdvancedAPI] params = "+JSON.stringify(e)),this.notifyBLECharacteristicValueChange(e)}asGetBLEDeviceServices(e){return this.getBLEDeviceServices(e)}asGetBLEDeviceRSSI(e){return new Promise((t,o)=>{e&&e.deviceId&&"string"==typeof e.deviceId?this.getBLEDeviceRSSI(e.deviceId).then(e=>{t({rssi:e})}).catch(e=>{o([[e,BLHErrorCode.SYSTEM_ERROR]])}):o([["invalidParams",BLHErrorCode.SYSTEM_ERROR]])})}asGetBLEDeviceCharacteristics(e){return this.getBLEDeviceCharacteristics(e)}asCreateBLEConnection(e){return e&&console.info("[AdvancedAPI] asCreateBLEConnection params = "+JSON.stringify(e)),this.createBLEConnection(e)}asCloseBLEConnection(e){return this.closeBLEConnection(e)}}class ASRouter{navigateTo(r){return new Promise((e,t)=>{var o,a;"string"!=typeof r.url?t(["param url",ErrorCode$1.PARAMETER_ERROR]):({url:o,urlParams:a}=getUrlParams(r.url),console.debug("[AdvancedAPI] navigateTo urlParams = %s",JSON.stringify(a)),router.pushUrl({url:o,params:a}).then(()=>{e()}).catch(e=>{console.error(`[AdvancedAPI] pushUrl failed, code is ${e.code}, message is `+e.message),t([e.message,e.code])}))})}redirectTo(r){return new Promise((e,t)=>{var o,a;"string"!=typeof r.url?t(["param url",ErrorCode$1.PARAMETER_ERROR]):({url:o,urlParams:a}=getUrlParams(r.url),console.debug("[AdvancedAPI] redirectTo urlParams = "+JSON.stringify(a)),router.replaceUrl({url:o,params:a}).then(()=>{e()}).catch(e=>{console.error(`[AdvancedAPI] replaceUrl failed, code is ${e.code}, message is `+e.message),t([e.message,e.code])}))})}switchTab(e){return new Promise(async(e,t)=>{t("[AdvancedAPI] switchTab do not support")})}navigateBack(r){return new Promise((e,t)=>{let{delta:o=1}=r;if("number"!=typeof(o=null===o?1:o))t(["parameter delta",ErrorCode$1.PARAMETER_ERROR]);else{var a=Number(router.getLength());o>a&&(o=a-1);try{for(let e=0;e{e=e.split("="),t[e[0]]=e[1]}),{url:e,urlParams:t}}class WifiBase{static isWifiActive(){return wifi.isWifiActive()}static scan(){return wifi.scan()}static ohoGetLinkedInfo(){return new Promise((o,a)=>{wifi.getLinkedInfo((e,t)=>{e?(console.log("[QAFAPI] get linked info error:"+e),a(e)):(console.log("[QAFAPI] get wifi linked info: "+JSON.stringify(t)),o(t))})})}static connectionChange(e){wifi.on("wifiConnectionChange",e)}static scanStateChange(e){wifi.on("wifiScanStateChange",e)}static getScanInfos(){return new Promise((t,o)=>{wifi.getScanInfos().then(e=>{t(e)}).catch(e=>{console.info("[QAFAPI] getScanInfos error "+JSON.stringify(e)),o(e)})})}}_defineProperty(WifiBase,"ConnState",{SCANNING:0,CONNECTING:1,AUTHENTICATING:2,OBTAINING_IPADDR:3,CONNECTED:4,DISCONNECTING:5,DISCONNECTED:6,UNKNOWN:7}),_defineProperty(WifiBase,"StateType",{OFF:0,ON:1}),_defineProperty(WifiBase,"ScanState",{SUCCESS:1,FAIL:0}),_dec$1=jsMethod({alias:"scan",common:!1}),_dec2$1=jsMethod({alias:"getConnectedWifi",common:!1}),_applyDecoratedDescriptor((_class$1=class{constructor(){this.SecureType={WPA:"wpa",WEP:"wep"}}isSecure(e=""){return!(!(e=e.toLowerCase()).includes(this.SecureType.WPA)&&!e.includes(this.SecureType.WEP))}getSignalStrength(e){return e+100}scan(){return new Promise((e,t)=>{WifiBase.isWifiActive()?WifiBase.scan()?e([["scan success"]]):t([["scan fail",WifiErrorCode.WIFI_NOT_TURNED_ON]]):t([["wifi not turned on",WifiErrorCode.WIFI_NOT_TURNED_ON]])})}getConnectedWifi(a){return new Promise((s,o)=>{WifiBase.isWifiActive()?WifiBase.ohoGetLinkedInfo().then(async e=>{if(e.connState===WifiBase.ConnState.DISCONNECTED)o([["wifi is not connected",ErrorCode$1.COMMON_ERROR]]);else if(a){var t={SSID:e.ssid};s([[t]])}else{let t={BSSID:e.bssid,SSID:e.ssid,frequency:e.frequency,signalStrength:this.getSignalStrength(e.rssi),secure:!1},o,a=await WifiBase.getScanInfos(),r=a.length;for(let e=0;e{wifi.isWifiActive()||wifi.enableWifi()?(console.debug("[AdvancedAPI] enableWifi success"),e()):(console.debug("[AdvancedAPI] enableWifi fail"),t(["wifi not turned on",WifiErrorCode.WIFI_NOT_TURNED_ON]))})}stopWifi(){return new Promise((e,t)=>{!wifi.isWifiActive()||wifi.disableWifi()?(console.debug("[AdvancedAPI] stopWifi success"),e()):(console.debug("[AdvancedAPI] stopWifi fail"),t(["system not support",ErrorCode$1.COMMON_ERROR]))})}getConnectedWifi(a={}){return new Promise((t,o)=>{var{partialInfo:e=!1}=a;super.getConnectedWifi(e).then(([[e]])=>{t({wifi:e})},e=>{o(...e)})})}getWifiList(e){return new Promise((t,o)=>{super.scan().then(([e=[]]=[])=>{t(...e)},e=>{o(...e)})})}onGetWifiList(e){"function"!=typeof e?console.error("[AdvancedAPI] param is invalid."):this.wifiScanCallbacks.push(e)}offGetWifiList(e){0<=(e=this.wifiScanCallbacks.indexOf(e))?this.wifiScanCallbacks.splice(e,1):this.wifiScanCallbacks=[]}connectWifi(n){return new Promise(async(t,o)=>{let{SSID:a,BSSID:e="",password:r="",maunal:s=!1}=n;if(isString(a))if(isString(e))if(isString(r)){try{if((await this.getConnectedWifi()).wifi.SSID===a)return void t()}catch(e){console.debug("[AdvancedAPI] wifi is not connected.")}try{var i=await wifi.addDeviceConfig({ssid:a,bssid:e,preSharedKey:r,securityType:3,isHiddenSsid:!1});console.debug("[AdvancedAPI] addDeviceConfig success netId = %d",i),this._connectByNetId.push(e=>{(e.wifi.SSID===a?t:o)()}),s?console.error("[AdvancedAPI] 不支持跳转系统wlan页面"):wifi.connectToNetwork(i)}catch(e){console.error("[AdvancedAPI] connectWifi addDeviceConfig fail err = "+e),o(["system not support",ErrorCode$1.COMMON_ERROR])}}else console.error("[AdvancedAPI] connectWifi invalid password"),o(["wifi password error",WifiErrorCode.PASSWORD_ERROR]);else console.error("[AdvancedAPI] connectWifi invalid BSSID"),o(["wifi BSSID error",WifiErrorCode.PASSWORD_ERROR]);else console.error("[AdvancedAPI] connectWifi invalid SSID"),o(["wifi SSID error",WifiErrorCode.PASSWORD_ERROR])})}onWifiConnected(e){"function"!=typeof e?console.error("[AdvancedAPI] param is invalid."):this.connectCallbacks.push(e)}offWifiConnected(e){0<=(e=this.connectCallbacks.indexOf(e))?this.connectCallbacks.splice(e,1):this.connectCallbacks=[]}connectionChange(){WifiBase.connectionChange(e=>{e===WifiBase.StateType.ON?this.getConnectedWifi().then(({wifi:e})=>{e.state=WifiBase.StateType.ON,this.triggerConnectCallbacks({wifi:e}),this.triggerConnectWithPartialInfo({wifi:e}),this.triggerConnectById({wifi:e})},()=>{var e={BSSID:"",signalStrength:0,state:WifiBase.StateType.ON,secure:!1,SSID:""};this.triggerConnectCallbacks({wifi:e}),this.triggerConnectWithPartialInfo({wifi:e})}):e===WifiBase.StateType.OFF&&(e={BSSID:"",signalStrength:0,state:WifiBase.StateType.OFF,secure:!1,SSID:""},this.triggerConnectCallbacks({wifi:e}),this.triggerConnectWithPartialInfo({wifi:e}))})}scanChange(){WifiBase.scanStateChange(e=>{e===WifiBase.ScanState.SUCCESS&&WifiBase.getScanInfos().then(e=>{console.debug("[AdvancedAPI] onGetWifiList getScanInfos success"),e=e.map(e=>({BSSID:e.bssid,SSID:e.ssid,frequency:e.frequency,signalStrength:super.getSignalStrength(e.rssi),secure:super.isSecure(e.capabilities)})),this.triggerScanCallbacks({wifiList:e})})})}triggerConnectCallbacks(t){console.debug("[AdvancedAPI] triggerConnectCallbacks"),t.errMsg="onWifiConnected:ok",t.errCode=0,this.connectCallbacks.forEach(e=>{e(t)})}triggerConnectById(t){console.debug("[AdvancedAPI] triggerConnectById"),this._connectByNetId.forEach(e=>{e(t)}),this._connectByNetId=[]}triggerScanCallbacks(t){console.debug("[AdvancedAPI] wifiScanCallbacks"),this.wifiScanCallbacks.forEach(e=>{e(t)})}onWifiConnectedWithPartialInfo(e){"function"!=typeof e?console.error("[AdvancedAPI] param is invalid."):this.connectWithPartialInfo.push(e)}offWifiConnectedWithPartialInfo(e){0<=(e=this.connectWithPartialInfo.indexOf(e))?this.connectWithPartialInfo.splice(e,1):this.connectWithPartialInfo=[]}triggerConnectWithPartialInfo(e){console.debug("[AdvancedAPI] triggerConnectWithPartialInfo");let t={SSID:e.wifi.SSID};this.connectWithPartialInfo.forEach(e=>{e({wifi:t})})}}let AUTH_RESULT={PERMISSION_CHECK_FAIL:201,PARAM_ERROR:401,FAIL:12500001,OPEN_ERROR:12500002,USER_CANCEL:12500003,TIME_OUT:12500004,TYPE_UNSUPPORTED:12500005,TRUSTED_LEVEL_UNSUPPORTED:12500006,TASK_BUSY:12500007,AUTHENTICATOR_LOCKED:12500009,NOT_ENROLLED:12500010};function toUint8Arr(e){var t,o=[];for(t of e){var a=t.charCodeAt(0);a<128?o.push(a):a<2048?(o.push(192+(a>>6)),o.push(128+(63&a))):a<65536&&(o.push(224+(a>>12)),o.push(128+(a>>6&63)),o.push(128+(63&a)))}return Uint8Array.from(o)}class ASAuthentication{start(n){return new Promise((t,o)=>{if("facial"!==(n&&n.requestAuthModes||""))o({errCode:90003,errMsg:"The authentication type is not supported."});else{var e=toUint8Arr(n.challenge),a=n&&n.authContent||"",r=userIAM_userAuth.UserAuthType.FACE,s=userIAM_userAuth.AuthTrustLevel.ATL1;try{var i=userIAM_userAuth.getAuthInstance(e,r,s);i.on("result",{callback:e=>{console.debug("[AdvancedAPI] authV9 result "+e.result),console.debug("[AdvancedAPI] authV9 token "+e.token),console.debug("[AdvancedAPI] authV9 remainAttempts "+e.remainAttempts),console.debug("[AdvancedAPI] authV9 lockoutDuration "+e.lockoutDuration),e.result===AUTH_RESULT.PERMISSION_CHECK_FAIL?o({errCode:90002,errMsg:"Permission verification failed."}):e.result===AUTH_RESULT.PARAM_ERROR?o({errCode:90004,errMsg:"Incorrect parameters."}):e.result===AUTH_RESULT.FAIL?o({errCode:90009,errMsg:"Authentication failed."}):e.result===AUTH_RESULT.OPEN_ERROR?o({errCode:90009,errMsg:"General operation error."}):e.result===AUTH_RESULT.USER_CANCEL?o({errCode:90008,errMsg:"The operation is canceled."}):e.result===AUTH_RESULT.TIME_OUT?o({errCode:90007,errMsg:"The operation is time-out."}):e.result===AUTH_RESULT.TYPE_UNSUPPORTED?o({errCode:90003,errMsg:"The authentication type is not supported."}):e.result===AUTH_RESULT.TRUSTED_LEVEL_UNSUPPORTED?o({errCode:90003,errMsg:"The authentication trust level is not supported."}):e.result===AUTH_RESULT.TASK_BUSY?o({errCode:90010,errMsg:"The authentication task is busy."}):e.result===AUTH_RESULT.AUTHENTICATOR_LOCKED?o({errCode:90010,errMsg:"The authenticator is locked."}):e.result===AUTH_RESULT.NOT_ENROLLED?o({errCode:90011,errMsg:"The type of credential has not been enrolled."}):t({authMode:"facial",resultJSON:"",resultJSONSignature:"",errCode:0,errMsg:void 0})}}),i.on("tip",{callback:e=>{switch(e.tip){case userIAM_userAuth.FaceTips.FACE_AUTH_TIP_TOO_BRIGHT:prompt.showToast({message:"光线太强,获取的图像太亮。"});break;case userIAM_userAuth.FaceTips.FACE_AUTH_TIP_TOO_DARK:prompt.showToast({message:"光线太暗,获取的图像太暗。"});break;case userIAM_userAuth.FaceTips.FACE_AUTH_TIP_TOO_CLOSE:prompt.showToast({message:"人脸距离设备过近。"});break;case userIAM_userAuth.FaceTips.FACE_AUTH_TIP_TOO_FAR:prompt.showToast({message:"人脸距离设备过远。"});break;case userIAM_userAuth.FaceTips.FACE_AUTH_TIP_TOO_HIGH:prompt.showToast({message:"设备太高,仅获取到人脸上部。"});break;case userIAM_userAuth.FaceTips.FACE_AUTH_TIP_TOO_LOW:prompt.showToast({message:"设备太低,仅获取到人脸下部。"});break;case userIAM_userAuth.FaceTips.FACE_AUTH_TIP_TOO_RIGHT:prompt.showToast({message:"设备太靠右,仅获取到人脸右部。"});break;case userIAM_userAuth.FaceTips.FACE_AUTH_TIP_TOO_LEFT:prompt.showToast({message:"设备太靠左,仅获取到人脸左部。"});break;case userIAM_userAuth.FaceTips.FACE_AUTH_TIP_TOO_MUCH_MOTION:prompt.showToast({message:"在图像采集过程中,用户人脸移动太快。"});break;case userIAM_userAuth.FaceTips.FACE_AUTH_TIP_POOR_GAZE:prompt.showToast({message:"没有正视摄像头。"});break;case userIAM_userAuth.FaceTips.FACE_AUTH_TIP_NOT_DETECTED:prompt.showToast({message:"没有检测到人脸信息。"});break;default:console.debug("[AdvancedAPI] %s",JSON.stringify(e))}}}),a&&(console.debug("[AdvancedAPI] showToast authContent = %s",a),prompt.showToast({message:a})),i.start(),console.debug("[AdvancedAPI] authV9 start success")}catch(e){console.debug("[AdvancedAPI] authV9 start error = %s",e),o({errCode:90007,errMsg:"General operation fail."})}}})}getSupportedType(){return console.debug("[AdvancedAPI] start getSupportedType"),new Promise(e=>{e({supportMode:["facial"]})})}isEnrolled(a){return console.debug("[AdvancedAPI] start isEnrolled"),new Promise((e,t)=>{var o=a&&a.checkAuthMode||"";"fingerPrint"===o?e({isEnrolled:!1,errMsg:""}):"facial"===o&&e({isEnrolled:!1,errMsg:"The type of credential has not been enrolled."})})}}class OhosSensorBase{static ohosSubscribeAccelerometer(e){let{interval:t,callback:o}=e;sensor.on(sensor.SensorType.SENSOR_TYPE_ID_ACCELEROMETER,e=>{o(e)},{interval:t})}static ohosUnsubscribeAccelerometer(){sensor.off(sensor.SensorType.SENSOR_TYPE_ID_ACCELEROMETER)}static ohosSubscribeCompass(e){let t=e.callback;sensor.on(sensor.SensorType.SENSOR_TYPE_ID_ORIENTATION,e=>{t(e)})}static ohosUnsubscribeCompass(){sensor.off(sensor.SensorType.SENSOR_TYPE_ID_ORIENTATION)}static ohosSubscribeGyroscope(e){let{intervalValue:t,callback:o}=e;sensor.on(sensor.SensorId.GYROSCOPE,e=>{o(e)},{interval:t})}static ohosUnsubscribeGyroscope(){sensor.off(sensor.SensorId.GYROSCOPE)}}let intervalType=[{label:"game",value:2e7},{label:"ui",value:6e7},{label:"normal",value:2e8}];class ASAccelerometer{constructor(){this.callBackSet=new Set,this.defaultInterval="normal"}onAccelerometerChange(o){return new Promise((e,t)=>{"function"!=typeof o||this.callBackSet.has(o)?t("param is invalid.",ErrorCode$1.PARAMETER_ERROR):(this.callBackSet.add(o),t=intervalType.find(e=>e.label===this.defaultInterval).value,OhosSensorBase.ohosSubscribeAccelerometer({interval:t,callback:e=>{var t,o={x:e.x,y:e.y,z:e.z};for(t of this.callBackSet.keys())t(o)}}),e())})}offAccelerometerChange(o){return new Promise((e,t)=>{"function"!=typeof o?(this.callBackSet.clear(),OhosSensorBase.ohosUnsubscribeAccelerometer(),e()):this.callBackSet.has(o)?(this.callBackSet.delete(o),0===this.callBackSet.size&&OhosSensorBase.ohosUnsubscribeAccelerometer(),e()):t("param is invalid.",ErrorCode$1.COMMON_ERROR)})}startAccelerometer(r){return new Promise((e,t)=>{let o=intervalType.find(e=>e.label===this.defaultInterval).value;var a;r.interval&&"string"==typeof r.interval&&(a=intervalType.find(e=>e.label===r.interval))&&(o=a.value),OhosSensorBase.ohosSubscribeAccelerometer({interval:o,callback:e=>{var t,o={x:e.x,y:e.y,z:e.z};for(t of this.callBackSet.keys())t(o)}}),e()})}stopAccelerometer(){return new Promise((e,t)=>{OhosSensorBase.ohosUnsubscribeAccelerometer(),e()})}}class ASCompass{constructor(){this.callBackCompassSet=new Set}onCompassChange(o){return new Promise(async(e,t)=>{"function"!=typeof o||this.callBackCompassSet.has(o)?t("param is invalid.",ErrorCode$1.PARAMETER_ERROR):(this.callBackCompassSet.add(o),OhosSensorBase.ohosSubscribeCompass({callback:e=>{var t,o={direction:e.alpha,accuracy:e.alpha?3:0};for(t of this.callBackCompassSet.keys())t(o)}}),e())})}offCompassChange(o){return new Promise(async(e,t)=>{"function"==typeof o&&this.callBackCompassSet.has(o)?(this.callBackCompassSet.delete(o),0===this.callBackCompassSet.size&&OhosSensorBase.ohosUnsubscribeCompass(),e("success")):t("param is invalid.",ErrorCode$1.PARAMETER_ERROR)})}startCompass(e){return new Promise(async(e,t)=>{OhosSensorBase.ohosSubscribeCompass({callback:e=>{var t,o={direction:e.alpha,accuracy:e.alpha?3:0};for(t of this.callBackCompassSet.keys())t(o)}}),e("success")})}stopCompass(){return new Promise(async(e,t)=>{OhosSensorBase.ohosUnsubscribeCompass(),e("success")})}}let intervalType$1=[{label:"game",value:2e7},{label:"ui",value:6e7},{label:"normal",value:2e8}];class ASGyroscope{constructor(){this.callBackGyroscopeSet=new Set}onGyroscopeChange(o){return new Promise((e,t)=>{"function"!=typeof o||this.callBackGyroscopeSet.has(o)?t("param is invalid.",ErrorCode$1.PARAMETER_ERROR):(this.callBackGyroscopeSet.add(o),e())})}startGyroscope(r={}){return new Promise((e,t)=>{let o=intervalType$1.find(e=>"normal"===e.label).value;var a;r.interval&&"string"==typeof r.interval&&(a=intervalType$1.find(e=>e.label===r.interval))&&(o=a.value),OhosSensorBase.ohosSubscribeGyroscope({intervalValue:o,callback:e=>{var t,o={x:e.x,y:e.y,z:e.z};for(t of this.callBackGyroscopeSet.keys())t(o)}}),e()})}stopGyroscope(){return new Promise((e,t)=>{OhosSensorBase.ohosUnsubscribeGyroscope(),e()})}}class ASContact{addPhoneContact(D){return new Promise(async(t,o)=>{try{var{authResults:e,dialogShownResults:a}=await abilityAccessCtrl.createAtManager().requestPermissionsFromUser(context,["ohos.permission.WRITE_CONTACTS"]);if(0!==e[0])return void o(["request permission fail",ErrorCode$1.USER_REJECT,e[0],a[0]]);console.debug("[AdvancedAPI] request WRITE_CONTACTS permission success")}catch(e){return void o(["request permission fail",ErrorCode$1.USER_REJECT])}var{photoFilePath:e,nickName:a="",lastName:r="",middleName:s="",firstName:i="",remark:n,mobilePhoneNumber:c,weChatNumber:l,addressCountry:d="",addressState:h="",addressCity:u="",addressStreet:p="",addressPostalCode:f,organization:A,url:g,workPhoneNumber:m,workFaxNumber:y,hostNumber:S,email:v,title:C,workAddressCountry:P="",workAddressState:E="",workAddressCity:b="",workAddressStreet:I="",workAddressPostalCode:T,homeFaxNumber:R,homePhoneNumber:k,homeAddressCountry:_="",homeAddressState:B="",homeAddressCity:O="",homeAddressStreet:w="",homeAddressPostalCode:L}=D;l||console.error("[AdvancedAPI] weChatNumber do not support."),i?(l={name:{familyName:r,middleName:s,givenName:i,fullName:r+s+i},nickName:{nickName:a},emails:[{email:v,displayName:"邮箱"}],phoneNumbers:[{phoneNumber:k,labelId:contact.PhoneNumber.NUM_HOME},{phoneNumber:c,labelId:contact.PhoneNumber.NUM_MOBILE},{phoneNumber:R,labelId:contact.PhoneNumber.NUM_FAX_HOME},{phoneNumber:y,labelId:contact.PhoneNumber.NUM_FAX_WORK},{phoneNumber:m,labelId:contact.PhoneNumber.NUM_WORK},{phoneNumber:S,labelId:contact.PhoneNumber.NUM_COMPANY_MAIN}],portrait:{uri:e},postalAddresses:[{city:O,country:_,postcode:L,street:w,postalAddress:_+B+O+w,labelId:contact.PostalAddress.ADDR_HOME},{city:b,country:P,postcode:T,street:I,postalAddress:P+E+b+I,labelId:contact.PostalAddress.ADDR_WORK},{city:u,country:d,postcode:f,street:p,postalAddress:d+h+u+p,labelId:contact.PostalAddress.CUSTOM_LABEL}],websites:[{website:g}],note:{noteContent:n},organization:{name:A,title:C}},contact.addContact(l).then(e=>{console.debug("[AdvancedAPI] addContact callback: success contactId = "+e),t()}).catch(e=>{console.debug("[AdvancedAPI] addContact callback: err->"+JSON.stringify(e)),o([e.data,e.code])})):(console.error("[AdvancedAPI] firstName is required."),o(["fail Missing required parameter `firstName`",ErrorCode$1.PARAMETER_ERROR]))})}}class ASVibrator{vibrate(){return new Promise((t,o)=>{this.triggerVibrate({duration:200}).then(e=>{t(e)}).catch(e=>{o([e.data,e.code])})})}vibrateLong(){return new Promise((t,o)=>{this.triggerVibrate({duration:400}).then(e=>{t(e)}).catch(e=>{o([e.data,e.code])})})}vibrateShort(){return new Promise((t,o)=>{this.triggerVibrate({duration:15}).then(e=>{t(e)}).catch(e=>{o([e.data,e.code])})})}triggerVibrate(a){return new Promise((t,o)=>{var e={type:"time",duration:a.duration};vibrator.startVibration(e,{id:0,usage:"alarm"}).then(e=>{console.debug("[AdvancedAPI] startVibration success"),t(e)},e=>{console.error("[AdvancedAPI] startVibration fail err = "+JSON.stringify(e)),o(e)}).catch(e=>{console.error("[AdvancedAPI] startVibration fail err = "+JSON.stringify(e)),o(e)})})}}class ASCapture{constructor(){this.captureCallback=null}onUserCaptureScreen(t){if(t)try{window.getLastWindow(globalThis.abilityContext).then(e=>{this.windowClass=e,this.captureCallback&&(this.windowClass.off("screenshot"),this.captureCallback=null),this.captureCallback=t,console.info("[AdvancedAPI] Succeeded in obtaining the top window. Listen to screenshot event.");try{this.windowClass.on("screenshot",function(){t("ohos not support path")})}catch(e){console.error("[AdvancedAPI] Failed to register callback. Cause: "+JSON.stringify(e))}}).catch(e=>{console.error("[AdvancedAPI] Failed to obtain the top window. Cause: "+JSON.stringify(e))})}catch(e){console.error("[AdvancedAPI] Failed to obtain the top window. Cause: "+JSON.stringify(e))}else console.error("[AdvancedAPI] params illegal, empty callback")}offUserCaptureScreen(t){try{window.getLastWindow(globalThis.abilityContext).then(e=>{this.windowClass=e,console.info("[AdvancedAPI] Succeeded in obtaining the top window. Unsubscribe screenshot event.");try{!t||this.captureCallback&&this.captureCallback===t?(this.windowClass.off("screenshot"),this.captureCallback=null):console.info("[AdvancedAPI] Invalid callback.")}catch(e){console.error("[AdvancedAPI] Failed to unregister callback. Cause: "+JSON.stringify(e))}}).catch(e=>{console.error("[AdvancedAPI] Failed to obtain the top window. Cause: "+JSON.stringify(e))})}catch(e){console.error("[AdvancedAPI] Failed to obtain the top window. Cause: "+JSON.stringify(e))}}}class ASKeyboard{constructor(){this.changeCallback=new Map}hideKeyboard(){return new Promise((e,t)=>{try{inputMethod.getController().hideTextInput().then(()=>{console.debug("[AdvancedAPI] Succeeded in hiding softKeyboard."),e()}).catch(e=>{console.error("[AdvancedAPI] Failed to hideSoftKeyboard: "+JSON.stringify(e)),t()})}catch(e){console.error("[AdvancedAPI] Failed to get inputMethod Controller. Cause: "+JSON.stringify(e)),t()}})}onKeyboardHeightChange(o){if(o)try{window.getLastWindow(globalThis.abilityContext).then(e=>{this.windowClass=e;let t=DisplayBase.ohosGetDisplay().densityPixels;this.changeCallback.has(o)||this.changeCallback.set(o,function(e){o({height:Math.round(e/t)})}),console.info("[AdvancedAPI] Succeeded in obtaining the top window. Listen to keyboard height change");try{this.windowClass.on("keyboardHeightChange",this.changeCallback.get(o))}catch(e){console.error("[AdvancedAPI] Failed to enable the listener for keyboard height changes. Cause: "+JSON.stringify(e))}}).catch(e=>{console.error("[AdvancedAPI] Failed to obtain the top window. Cause: "+JSON.stringify(e))})}catch(e){console.error("[AdvancedAPI] Failed to obtain the top window. Cause: "+JSON.stringify(e))}else console.error("[AdvancedAPI] params illegal, empty callback")}offKeyboardHeightChange(t){try{window.getLastWindow(globalThis.abilityContext).then(e=>{this.windowClass=e,console.info("[AdvancedAPI] Succeeded in obtaining the top window. Unsubscribe keyboard change event.");try{t?this.changeCallback.has(t)?(this.windowClass.off("keyboardHeightChange",this.changeCallback.get(t)),this.changeCallback.delete(t)):console.info("[AdvancedAPI] Invalid callback."):(this.windowClass.off("keyboardHeightChange"),this.changeCallback.clear())}catch(e){console.error("[AdvancedAPI] Failed to unregister callback. Cause: "+JSON.stringify(e))}}).catch(e=>{console.error("[AdvancedAPI] Failed to obtain the top window. Cause: "+JSON.stringify(e))})}catch(e){console.error("[AdvancedAPI] Failed to obtain the top window. Cause: "+JSON.stringify(e))}}}class FileioBase{static ohosOpendirSync(e){return new OhosOpendir(e)}static ohosReadSync(e,t){return fs.readSync(e,t)}static ohosUnlinkSync(e){return fs.unlinkSync(e)}static ohosCopy(e,t,o=0){return fs.copyFile(e,t,o)}static ohosMkdirSync(e,t=0){return fs.mkdirSync(e)}static ohosReadTextSync(e,t){return fs.readTextSync(e,t)}static ohosStatSync(e){return fs.statSync(e)}static ohosOpenSync(e,t,o=0){return e&&"string"==typeof e&&e.startsWith("/data/storage/")&&(e=fileuri.getUriFromPath(e)),fs.openSync(e,t)}static ohosWriteSync(e,t,o={}){return fs.writeSync(e,t,o)}static ohosAccessSync(e,t=0){return fs.accessSync(e)}}class OhosOpendir{constructor(e){this.dir=fs.listFileSync(e)}ohosReadsync(){return this.dir}}class WantConstantBase{static getAction(e){return wantConstant.Action[e]}}let version="3.7.7",VERSION=version,_hasBuffer="function"==typeof Buffer,_TD="function"==typeof TextDecoder?new TextDecoder:void 0,_TE="function"==typeof TextEncoder?new TextEncoder:void 0,b64ch="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",b64chs=Array.prototype.slice.call(b64ch),b64tab=(e=>{let o={};return e.forEach((e,t)=>o[e]=t),o})(b64chs),b64re=/^(?:[A-Za-z\d+\/]{4})*?(?:[A-Za-z\d+\/]{2}(?:==)?|[A-Za-z\d+\/]{3}=?)?$/,_fromCC=String.fromCharCode.bind(String),_U8Afrom="function"==typeof Uint8Array.from?Uint8Array.from.bind(Uint8Array):e=>new Uint8Array(Array.prototype.slice.call(e,0)),_mkUriSafe=e=>e.replace(/=/g,"").replace(/[+\/]/g,e=>"+"==e?"-":"_"),_tidyB64=e=>e.replace(/[^A-Za-z0-9\+\/]/g,""),btoaPolyfill=t=>{let o,a,r,s,i="",e=t.length%3;for(let e=0;e>18&63]+b64chs[o>>12&63]+b64chs[o>>6&63]+b64chs[63&o]}return e?i.slice(0,e-3)+"===".substring(e):i},_btoa="function"==typeof btoa?e=>btoa(e):_hasBuffer?e=>Buffer.from(e,"binary").toString("base64"):btoaPolyfill,_fromUint8Array=_hasBuffer?e=>Buffer.from(e).toString("base64"):o=>{var a=[];for(let e=0,t=o.length;et?_mkUriSafe(_fromUint8Array(e)):_fromUint8Array(e),cb_utob=e=>{var t;return e.length<2?(t=e.charCodeAt(0))<128?e:t<2048?_fromCC(192|t>>>6)+_fromCC(128|63&t):_fromCC(224|t>>>12&15)+_fromCC(128|t>>>6&63)+_fromCC(128|63&t):(t=65536+1024*(e.charCodeAt(0)-55296)+(e.charCodeAt(1)-56320),_fromCC(240|t>>>18&7)+_fromCC(128|t>>>12&63)+_fromCC(128|t>>>6&63)+_fromCC(128|63&t))},re_utob=/[\uD800-\uDBFF][\uDC00-\uDFFFF]|[^\x00-\x7F]/g,utob=e=>e.replace(re_utob,cb_utob),_encode=_hasBuffer?e=>Buffer.from(e,"utf8").toString("base64"):_TE?e=>_fromUint8Array(_TE.encode(e)):e=>_btoa(utob(e)),encode=(e,t=!1)=>t?_mkUriSafe(_encode(e)):_encode(e),encodeURI$1=e=>encode(e,!0),re_btou=/[\xC0-\xDF][\x80-\xBF]|[\xE0-\xEF][\x80-\xBF]{2}|[\xF0-\xF7][\x80-\xBF]{3}/g,cb_btou=e=>{switch(e.length){case 4:var t=((7&e.charCodeAt(0))<<18|(63&e.charCodeAt(1))<<12|(63&e.charCodeAt(2))<<6|63&e.charCodeAt(3))-65536;return _fromCC(55296+(t>>>10))+_fromCC(56320+(1023&t));case 3:return _fromCC((15&e.charCodeAt(0))<<12|(63&e.charCodeAt(1))<<6|63&e.charCodeAt(2));default:return _fromCC((31&e.charCodeAt(0))<<6|63&e.charCodeAt(1))}},btou=e=>e.replace(re_btou,cb_btou),atobPolyfill=t=>{if(t=t.replace(/\s+/g,""),!b64re.test(t))throw new TypeError("malformed base64.");t+="==".slice(2-(3&t.length));let o,a="",r,s;for(let e=0;e>16&255):64===s?_fromCC(o>>16&255,o>>8&255):_fromCC(o>>16&255,o>>8&255,255&o);return a},_atob="function"==typeof atob?e=>atob(_tidyB64(e)):_hasBuffer?e=>Buffer.from(e,"base64").toString("binary"):atobPolyfill,_toUint8Array=_hasBuffer?e=>_U8Afrom(Buffer.from(e,"base64")):e=>_U8Afrom(_atob(e).split("").map(e=>e.charCodeAt(0))),toUint8Array=e=>_toUint8Array(_unURI(e)),_decode=_hasBuffer?e=>Buffer.from(e,"base64").toString("utf8"):_TD?e=>_TD.decode(_toUint8Array(e)):e=>btou(_atob(e)),_unURI=e=>_tidyB64(e.replace(/[-_]/g,e=>"-"==e?"+":"/")),decode=e=>_decode(_unURI(e)),isValid=e=>"string"==typeof e&&(e=e.replace(/\s+/g,"").replace(/={0,2}$/,""),!/[^\s0-9a-zA-Z\+/]/.test(e)||!/[^\s0-9a-zA-Z\-_]/.test(e)),_noEnum=e=>({value:e,enumerable:!1,writable:!0,configurable:!0}),extendString=function(){var e=(e,t)=>Object.defineProperty(String.prototype,e,_noEnum(t));e("fromBase64",function(){return decode(this)}),e("toBase64",function(e){return encode(this,e)}),e("toBase64URI",function(){return encode(this,!0)}),e("toBase64URL",function(){return encode(this,!0)}),e("toUint8Array",function(){return toUint8Array(this)})},extendUint8Array=function(){var e=(e,t)=>Object.defineProperty(Uint8Array.prototype,e,_noEnum(t));e("toBase64",function(e){return fromUint8Array(this,e)}),e("toBase64URI",function(){return fromUint8Array(this,!0)}),e("toBase64URL",function(){return fromUint8Array(this,!0)})},extendBuiltins=()=>{extendString(),extendUint8Array()},gBase64={version:version,VERSION:VERSION,atob:_atob,atobPolyfill:atobPolyfill,btoa:_btoa,btoaPolyfill:btoaPolyfill,fromBase64:decode,toBase64:encode,encode:encode,encodeURI:encodeURI$1,encodeURL:encodeURI$1,utob:utob,btou:btou,decode:decode,isValid:isValid,fromUint8Array:fromUint8Array,toUint8Array:toUint8Array,extendString:extendString,extendUint8Array:extendUint8Array,extendBuiltins:extendBuiltins};class ASImage{constructor(){_defineProperty(this,"getArrayBuffer",async(e,t,o,a,r)=>{var s,i,n;return void 0!==a||void 0!==r?(a=r||a||0,n=image.createImageSource(t),i=image.createImagePacker(),r=(s=await n.getImageInfo()).size.width/r,n=await n.createPixelMap({desiredSize:{width:a,height:s.size.height/r}}),await i.packing(n,{format:"image/jpeg",quality:e})):(a=image.createImageSource(t),s=image.createImagePacker(),r={format:"image/jpeg",quality:e},i=await a.getImageInfo(),n=await a.createPixelMap({desiredSize:{width:i.size.width,height:i.size.height}}),await s.packing(n,r))})}chooseImage(n){return n=n||{},new Promise(async(e,t)=>{var o=await MediaLibraryBase.getPermissions();if(-1===o.perNum)return t(["permission fail",ErrorCode$1.USER_REJECT,o.perNum,o.dialogShownResults]);if(n.count&&"number"!=typeof n.count)return t(['chooseImage:fail parameter `count`. Expected Number with value NaN, got String with value "'+n.count+'".',ErrorCode$1.PARAMETER_ERROR]);n.count<1&&(n.count=9);let a=[];if(n.sourceType&&1===n.sourceType.length&&n.sourceType.includes("camera")){if(o=await bundleManager.getBundleInfoForSelf(bundleManager.BundleFlag.GET_BUNDLE_INFO_DEFAULT),0!==(o=await context.startAbilityForResult({action:WantConstantBase.getAction("ACTION_IMAGE_CAPTURE"),parameters:{uri:"capture",callBundleName:o.name}})).resultCode)return t(["Failed to pull up camera app",ErrorCode$1.SERVICE_UNAVIALABLE]);if(a=[o.want.parameters.resourceUri],!o.want.parameters.resourceUri)return}else(o=new picker.PhotoSelectOptions).MIMEType=picker.PhotoViewMIMETypes.IMAGE_TYPE,o.maxSelectNumber=n.count,o=await(new picker.PhotoViewPicker).select(o),a=o.photoUris;if(!a)return t(["get uri fail",ErrorCode$1.SERVICE_UNAVIALABLE]);if("cancel"!==a){var r,s=[],i=[];for(let e=0;e{try{var o,a,r,s,i,n=c.src;return isFileUri(n)?(a={0:"up",90:"right",180:"down",270:"left"}[(o=await getFileAssetFromUri(n)).orientation],e({width:o.width,height:o.height,path:n,orientation:a,type:o.displayName.split(".").pop()})):isSandboxPath(n)?(r=image.createImageSource(switchInternalToHapSandBox(n)),s=n.split(".").pop(),e({width:(i=await r.getImageInfo()).size.width,height:i.size.height,path:c.src,orientation:"up",type:s})):t(["get uri fail",ErrorCode$1.SERVICE_UNAVIALABLE])}catch(e){return t(["get uri fail",ErrorCode$1.SERVICE_UNAVIALABLE])}})}saveImageToPhotosAlbum(v){return new Promise(async(o,e)=>{try{var t,a,r,s,i,n,c=v.filePath;if("string"!=typeof c)return e(["filePath format is not supported.",ErrorCode$1.PARAMETER_ERROR]);if(isFileUri(c))a=getFdFromUriOrSandBoxPath(t=c),r=fs.statSync(a).size,s=new ArrayBuffer(r),FileioBase.ohosReadSync(a,s),i=await getFileAssetFromUri(t),n="IMAGE_"+(new Date).getTime()+"_"+i.displayName,o({path:await saveMedia(photoAccessHelper.PhotoType.IMAGE,n,t,s)});else if(isSandboxPath(c)){let t=c;if(t.startsWith("internal://")&&(t=switchInternalToHapSandBox(c)),fs.accessSync(t)){var l=fs.openSync(t,fs.OpenMode.READ_ONLY);if(l){var d=l.fd,h=fs.statSync(t).size,u=new ArrayBuffer(h);FileioBase.ohosReadSync(d,u);let e="IMAGE_"+(new Date).getTime()+"_"+t.split("/").splice(-1,1).toString();e.includes(".")||(e+=".jpg"),t=fileuri.getUriFromPath(t),o({path:await saveMedia(photoAccessHelper.PhotoType.IMAGE,e,t,u)})}else e(["saveImageToPhotosAlbum fail, src not exist.",ErrorCode$1.PARAMETER_ERROR])}else e(["saveImageToPhotosAlbum fail, src not exist.",ErrorCode$1.PARAMETER_ERROR])}else{if(c.startsWith("data:image/")){var p=c.split(";");if(2===p.length&&p[1].startsWith("base64")){var f=p[0].replace("data:image/",""),A=gBase64.atob(c.split(",")[1]),g="IMAGE_"+(new Date).getTime()+"."+f,m=new ArrayBuffer(A.length),y=new Uint8Array(m);for(let e=0;e{let n=switchInternalToHapSandBox(p.src),c=0<=(n.split("/").pop()||"").indexOf(".")&&p.src.toLowerCase().split(".").pop()||"jpg",l=p.quality||80,t=await MediaLibraryBase.getPermissions();if(-1===t.perNum)return e(["permission fail",ErrorCode$1.USER_REJECT,t.perNum,t.dialogShownResults]);if(l&&"number"!=typeof l)return e(["compressImage fail, input parameter quality is illegal.",ErrorCode$1.PARAMETER_ERROR]);(100{console.info("AVPlayer seek succeeded, seek time is "+e),this.onSeekedCallback&&this.onSeekedCallback({})}),this.avPlayer.on("error",e=>{console.error(`Invoke avPlayer failed, code is ${e.code}, message is `+e.message),this.avPlayer.reset(),this.onErrorCallback&&this.onErrorCallback(e)}),this.avPlayer.on("stateChange",async(e,t)=>{switch(e){case"idle":console.info("AVPlayer state idle called."),this.stopFlag&&(this.avPlayer.url=this.tempSrc,this.stopFlag=!1);break;case"initialized":console.info("AVPlayerstate initialized called."),this.avPlayer.prepare().then(()=>{console.info("AVPlayer prepare succeeded."),this.onCanplayCallback&&this.onCanplayCallback({})},e=>{console.error(`Invoke prepare failed, code is ${e.code}, message is `+e.message)});break;case"prepared":console.info("AVPlayer state prepared called."),0===this.count&&this.autoplayS&&(this.avPlayer.play(),this.onPlayCallback&&this.onPlayCallback({}),this.startTimeS)&&(this.onSeekingCallback&&this.onSeekingCallback({}),this.avPlayer.seek(this.startTimeS)),this.count++,this.avPlayer.loop=this.tempLoop,this.avPlayer.setVolume(this.volumeS),this.avPlayer.setSpeed(this.playbackRateS);break;case"playing":console.info("AVPlayer state playing called."),this.avPlayer.loop=this.tempLoop,this.avPlayer.setVolume(this.volumeS),this.avPlayer.setSpeed(this.playbackRateS);break;case"paused":console.info("AVPlayer state paused called."),this.avPlayer.loop=this.tempLoop,this.avPlayer.setVolume(this.volumeS),this.avPlayer.setSpeed(this.playbackRateS);break;case"completed":console.info("AVPlayer state completed called."),this.onEndedCallback&&this.onEndedCallback({}),this.avPlayer.loop=this.tempLoop,this.avPlayer.setVolume(this.volumeS),this.avPlayer.setSpeed(this.playbackRateS);break;case"stopped":console.info("AVPlayer state stopped called."),this.avPlayer.reset(),this.stopFlag=!0;break;case"released":console.info("AVPlayer state released called.");break;default:console.info("AVPlayer state unknown called.")}}),this.avPlayer.on("timeUpdate",e=>{this.onTimeUpdateCallback&&this.onTimeUpdateCallback(e/1e3)}),this.avPlayer.on("bufferingUpdate",(e,t)=>{console.info(`[AdvancedAPI] avPlayer bufferingUpdate ${e} `+t),3===e&&0!==t&&(this.bufferedS=t,this.avPlayer.currentTime/1e3>=this.avPlayer.duration*t/1e5)&&this.onWaitingCallback&&this.onWaitingCallback({})}),this.avPlayer.on("audioInterrupt",e=>{console.info("[AdvancedAPI] audioInterrupt:"+JSON.stringify(e)),e.hintType===audio.InterruptHint.INTERRUPT_HINT_PAUSE&&(this.avPlayer.pause(),this.onPauseCallback)&&this.onPauseCallback({})}),this.avPlayer.on("endOfStream",()=>{console.info("[AdvancedAPI] rePlay:endOfStream success"),this.avPlayer.loop&&(this.avPlayer.play(),this.startTimeS)&&(this.onSeekingCallback&&this.onSeekingCallback({}),this.avPlayer.seek(this.startTimeS))})}get duration(){return this.avPlayer?this.avPlayer.duration/1e3:(console.error("[AdvancedAPI] avPlayer is not exist, get duration fail"),0)}get currentTime(){return this.avPlayer?this.avPlayer.currentTime/1e3:(console.error("[AdvancedAPI] avPlayer is not exist, get currentTime fail"),0)}get paused(){return this.avPlayer?this.avPlayer.state===StateType.PAUSED:(console.error("[AdvancedAPI] avPlayer is not exist, get paused fail"),!0)}get loop(){return this.tempLoop}set loop(e){"boolean"!=typeof e?console.error(`[AdvancedAPI] loop: ${e} is invalid`):(this.tempLoop=e,this.avPlayer&&[StateType.PREPARED,StateType.PLAYING,StateType.PAUSED,StateType.COMPLETED].includes(this.avPlayer.state)&&(console.info("current state is "+this.avPlayer.state+" can set loop"),this.avPlayer.loop=e))}get volume(){return this.volumeS}set volume(e){"number"!=typeof e?console.error(`[AdvancedAPI] volume: ${e} is invalid`):(this.volumeS=e,this.avPlayer&&[StateType.PREPARED,StateType.PLAYING,StateType.PAUSED,StateType.COMPLETED].includes(this.avPlayer.state)&&(console.info("current state is "+this.avPlayer.state+" can set volume"),this.avPlayer.setVolume(e)))}get autoplay(){return this.autoplayS}set autoplay(e){"boolean"!=typeof e?console.error(`[AdvancedAPI] autoplay: ${e} is invalid`):this.autoplayS=e}get startTime(){return this.startTimeS/1e3}set startTime(e){"number"!=typeof e?console.error(`[AdvancedAPI] startTIme: ${e} is invalid`):this.startTimeS=1e3*e}get src(){return this.avPlayer?this.avPlayer.url:(console.error("[AdvancedAPI] avPlayer is not exist, get src fail"),"")}set src(e){if("string"!=typeof e)console.error(`[AdvancedAPI] src: ${e} is invalid`);else if(this.avPlayer)if(e&&(e.startsWith("http:")||e.startsWith("https:")||e.startsWith("datashare:")||e.startsWith("internal://")))if(this.avPlayer.state!==StateType.IDLE)console.error("current state is "+this.avPlayer.state+" can not set url");else{let t;if(e.startsWith("http:")||e.startsWith("https:"))t=e;else if(e.startsWith("internal://"))try{var o=switchInternalToHapSandBox(e),a=fs.openSync(o,fs.OpenMode.READ_ONLY).fd;t="fd://"+a}catch(o){console.info(""+JSON.stringify(o))}else if(e.startsWith("datashare:"))try{var r=MediaLibraryBase.getMedia(),s=MediaLibraryBase.getFileKey(),i=MediaLibraryBase.getMediaType("AUDIO"),n={selections:s.MEDIA_TYPE+"= ?",selectionArgs:[i.toString()],uri:e};return void r.getFileAssets(n).then(e=>{e.getFirstObject().then(e=>{MediaLibraryBase.getFd(e).then(e=>{t="fd://"+e,this.avPlayer.url&&t!==this.avPlayer.url&&this.avPlayer.reset(),this.avPlayer.url=t})})})}catch(o){return void console.error(`[AdvancedAPI] src: ${e} is invalid`)}this.avPlayer.url&&t!==this.avPlayer.url&&this.avPlayer.reset(),this.avPlayer.url=t,this.tempSrc=t}else console.error(`[AdvancedAPI] src: ${e} is invalid`);else console.error("[AdvancedAPI] avPlayer is not exist, set src fail")}get buffered(){return this.avPlayer?this.avPlayer.duration*this.bufferedS/1e5:(console.error("[AdvancedAPI] avPlayer is not exist, get buffered fail"),0)}get playbackRate(){return this.playbackRateS}set playbackRate(e){"number"!=typeof e?console.error(`[AdvancedAPI] speed: ${e} is invalid`):(e=e<=.75?media.PlaybackSpeed.SPEED_FORWARD_0_75_X:.75t(["getVideoInfo is not support!"]))}saveVideoToPhotosAlbum(e){return new Promise(async(t,o)=>{var a,r,s,i=e.filePath;if("string"!=typeof i)return o(["filePath format is not supported.",ErrorCode$1.PARAMETER_ERROR]);if(console.debug("[AdvancedAPI] filePath:",i),isFileUri(i))r=getFdFromUriOrSandBoxPath(a=i),s=fs.statSync(r).size,s=new ArrayBuffer(s),FileioBase.ohosReadSync(r,s),r=await getFileAssetFromUri(a),r="VIDEO_"+(new Date).getTime()+"_"+r.displayName,t({path:await saveMedia(photoAccessHelper.PhotoType.VIDEO,r,a,s)});else{if(isSandboxPath(i)){let e=i;return e.startsWith("internal://")&&(e=switchInternalToHapSandBox(e)),fs.accessSync(e)&&(r=fs.openSync(e,fs.OpenMode.READ_ONLY))?(a=r.fd,s=fs.statSync(e).size,r=new ArrayBuffer(s),FileioBase.ohosReadSync(a,r),s="VIDEO_"+(new Date).getTime()+"_"+i.split("/").splice(-1,1).toString(),e=fileuri.getUriFromPath(e),void t({path:await saveMedia(photoAccessHelper.PhotoType.VIDEO,s,e,r)})):void o(["saveVideoToPhotosAlbum fail, src not exist.",ErrorCode$1.PARAMETER_ERROR])}o(["filePath format is not supported.",ErrorCode$1.PARAMETER_ERROR])}})}}let StateType$1={IDLE:"idle",PLAYING:"playing",PAUSED:"paused",STOPPED:"stopped",ERROR:"error"};function createAVSession(t){console.debug("[AdvancedAPI] createAVSession begin"),avSession.createAVSession(context,"player","audio").then(e=>{console.debug("[AdvancedAPI] createAVSession succeed"),t.avSession=e})}function destroyAVSession(e){console.debug("[AdvancedAPI] destroyAVSession begin"),null===e.avSession?console.debug("[AdvancedAPI] avSession is null"):e.avSession.destroy()}function startBackgroundTask(){AbilityBase.getAbilityInfo().then(e=>{e={wants:[{bundleName:e.bundleName,abilityName:e.name}],operationType:wantAgent.OperationType.START_ABILITY,requestCode:0,wantAgentFlags:[wantAgent.WantAgentFlags.UPDATE_PRESENT_FLAG]},wantAgent.getWantAgent(e).then(e=>backgroundTaskManager.startBackgroundRunning(context,backgroundTaskManager.BackgroundMode.AUDIO_PLAYBACK,e)).then(()=>{console.debug("[AdvancedAPI] start bg operation succeeded")}).catch(e=>{console.error("[AdvancedAPI] start bg operation failed Cause: "+e)})})}function stopBackgroundTask(){backgroundTaskManager.stopBackgroundRunning(context).then(()=>{console.debug("[AdvancedAPI] stop operation succeeded")}).catch(e=>{console.error("[AdvancedAPI] stop operation fail cause: "+JSON.stringify(e))})}class ASBGAudio{constructor(){this.backgroundAudioManager=new BackgroundAudioManager}}class BackgroundAudioManager{constructor(){this.bufferedS=0,this.avSession=null,this.startTimeS=0,this.onWaitingCallback=null,this.titleS=null,this.epnameS=null,this.singerS=null,this.coverImgUrlS=null,this.webUrlS=null,this.protocolS="http",this.onFinishCallback=null,this.tempSrc="",this.onCanplayCallback=null,this.onPlayCallback=null,this.onPauseCallback=null,this.onStopCallback=null,this.onTimeUpdateCallback=null,this.onErrorCallback=null,this.init()}init(){this.audioPlayer=media.createAudioPlayer(),this.audioPlayer.on("finish",()=>{destroyAVSession(this),stopBackgroundTask(),this.onFinishCallback&&this.onFinishCallback({})}),this.audioPlayer.on("dataLoad",()=>{this.onCanplayCallback&&this.onCanplayCallback({})}),this.audioPlayer.on("bufferingUpdate",(e,t)=>{console.info(`[AdvancedAPI] bgAudio bufferingUpdate ${e} `+t),3===e&&0!==t&&(this.bufferedS=t,this.audioPlayer.currentTime/1e3>=this.audioPlayer.duration*t/1e5)&&this.onWaitingCallback&&this.onWaitingCallback({})}),this.audioPlayer.on("audioInterrupt",e=>{console.info("[AdvancedAPI] audioInterrupt:"+JSON.stringify(e)),e.hintType===audio.InterruptHint.INTERRUPT_HINT_PAUSE&&this.audioPlayer.pause(),e.hintType===audio.InterruptHint.INTERRUPT_HINT_RESUME&&this.audioPlayer.play()}),this.audioPlayer.on("play",()=>{this.onPlayCallback&&this.onPlayCallback({})}),this.audioPlayer.on("pause",()=>{this.onPauseCallback&&this.onPauseCallback({})}),this.audioPlayer.on("timeUpdate",e=>{this.onTimeUpdateCallback&&this.onTimeUpdateCallback(e/1e3)}),this.audioPlayer.on("error",e=>{this.onErrorCallback&&this.onErrorCallback(e)})}get duration(){return this.audioPlayer.duration/1e3}get currentTime(){return this.audioPlayer.currentTime/1e3}get paused(){return this.audioPlayer.state===StateType$1.PAUSED}get src(){return this.audioPlayer.src}set src(t){if("string"!=typeof t)console.error(`[AdvancedAPI] src: ${t} is invalid`);else if(t&&(t.startsWith("http:")||t.startsWith("https:")||isFileUri(t)||isSandboxPath(t))){let e;if(t.startsWith("http:")||t.startsWith("https:"))e=t;else if(isFileUri(t)||isSandboxPath(t))try{var o=getFdFromUriOrSandBoxPath(t);e="fd://"+o}catch(e){console.info(""+JSON.stringify(e))}this.audioPlayer.src&&e!==this.audioPlayer.src&&this.audioPlayer.reset(),this.audioPlayer.src=e,this.tempSrc=t,this.audioPlayer.play(),this.startTimeS&&this.audioPlayer.seek(this.startTimeS),startBackgroundTask(),createAVSession(this)}else console.error(`[AdvancedAPI] src: ${t} is invalid`)}get startTime(){return this.startTimeS/1e3}set startTime(e){this.startTimeS=1e3*e}get buffered(){return this.audioPlayer.duration*this.bufferedS/1e5}get title(){return this.titleS}set title(e){this.titleS=e}get epname(){return this.epnameS}set epname(e){this.epnameS=e}get singer(){return this.singerS}set singer(e){this.singerS=e}get coverImgUrl(){return this.coverImgUrlS}set coverImgUrl(e){this.coverImgUrlS=e}get webUrl(){return this.webUrlS}set webUrl(e){this.webUrlS=e}get protocol(){return this.protocolS}set protocol(e){this.protocolS=e}play(){var e=this.audioPlayer.state;[StateType$1.PAUSED,StateType$1.STOPPED,StateType$1.IDLE].includes(e)&&(this.tempSrc&&""===this.audioPlayer.src&&(this.src=this.tempSrc),this.audioPlayer.play(),startBackgroundTask(),createAVSession(this))}pause(){var e=this.audioPlayer.state;StateType$1.PLAYING===e&&this.audioPlayer.pause()}stop(){var e=this.audioPlayer.state;[StateType$1.PAUSED,StateType$1.PLAYING].includes(e)&&(this.audioPlayer.stop(),this.onStopCallback&&this.onStopCallback({}),this.audioPlayer.release(),this.init(),destroyAVSession(this),stopBackgroundTask())}seek(e){var t=this.audioPlayer.state;[StateType$1.PAUSED,StateType$1.PLAYING].includes(t)&&this.audioPlayer.seek(1e3*e)}onCanplay(e){this.onCanplayCallback=e}onPlay(e){this.onPlayCallback=e}onPause(e){this.onPauseCallback=e}onStop(e){this.onStopCallback=e}onEnded(e){this.onFinishCallback=e}onTimeUpdate(e){this.onTimeUpdateCallback=e}onError(e){this.onErrorCallback=e}onPrev(e){console.info("ios only")}onNext(e){console.info("ios only")}onWaiting(e){this.onWaitingCallback=e}}class SecurityBase{static rsa(a,r){return new Promise(async(e,t)=>{var o;try{await(o=cryptoFramework.createMd(a)).update(r),e((await o.digest()).data)}catch(e){console.error("[QAFAPI]: rsa fail error code: "+e.code+", message is: "+e.message),t(e)}})}}class FileCallback{constructor({success:e,fail:t,complete:o}){checkDataType(e,!1,"function")&&(this.successFn=e),checkDataType(t,!1,"function")&&(this.failFn=t),checkDataType(o,!1,"function")&&(this.completeFn=o)}success(...e){if(this.successFn)try{this.successFn(...e)}catch(e){console.error(e)}if(this.completeFn)try{this.completeFn(...e)}catch(e){console.error(e)}}fail(...e){if(this.failFn)try{this.failFn(...e)}catch(e){console.error(e)}if(this.completeFn)try{this.completeFn(...e)}catch(e){console.error(e)}}}let openMode=fs.OpenMode,ERROR={PARAMETER_ERROR:1001},modeReflect={ax:"a","ax+":"a+",wx:"w","wx+":"w+"},ENCODING=["utf8","utf-8","ascii","base64","binary","hex","ucs2","ucs-2","utf16le","utf-16le","latin1"];function getOpenMode(e){let t;switch(e){case"a":t=openMode.CREATE|openMode.APPEND;break;case"a+":t=openMode.CREATE|openMode.READ_WRITE|openMode.APPEND;break;case"as":t=openMode.SYNC|openMode.CREATE|openMode.APPEND;break;case"as+":t=openMode.SYNC|openMode.CREATE|openMode.READ_WRITE|openMode.APPEND;break;case"r":t=openMode.READ_ONLY;break;case"r+":t=openMode.READ_WRITE;break;case"w":t=openMode.CREATE|openMode.WRITE_ONLY|openMode.TRUNC;break;case"w+":t=openMode.CREATE|openMode.READ_WRIT|openMode.TRUNC}return t}function getFileTypeMode(e){return e.isBlockDevice()?24576:e.isCharacterDevice()?8192:e.isDirectory()?16384:e.isFIFO()?4096:e.isFile()?32768:e.isSocket()?49152:e.isSymbolicLink()?40960:void 0}function mkdirRecursive(e,t){var o=t.shift();e=e||o?e+"/"+o:"",o&&!fs.accessSync(e)&&fs.mkdirSync(e),0{e?(console.debug("[AdvancedAPI] file access exist"),r.success({errMsg:"access:ok"})):r.fail({errMsg:"access:fail no such file or directory"})},e=>{console.debug("[AdvancedAPI] access failed with error message: %s, code = %d",e.message,e.code)}):r.fail({errMsg:"access:fail parameter error: parameter.path should be String",errno:ERROR$1.PARAMETER_ERROR})}accessSync(e){if(!checkDataType(e,!0,"string"))throw new Error("accessSync:fail path must be a string");if(!fs.accessSync(e))throw new Error("accessSync:fail no such file or directory")}appendFile({filePath:e,data:o,encoding:t=DEFAULT_ENCODING,success:a,fail:r,complete:s}){let i=new FileCallback({success:a,fail:r,complete:s});if(checkDataType(e,!0,"string"))if(checkDataType(o,!0,["string","arraybuffer"]))if(fs.accessSync(e)){let t=fs.openSync(e,fs.OpenMode.READ_WRITE|fs.OpenMode.APPEND);fs.write(t.fd,o).then(e=>{i.success({errMsg:"appendFile:ok"}),fs.closeSync(t)}).catch(e=>{console.error("[AdvancedAPI] appendFile failed with error message: "+e.message+", error code: "+e.code),i.fail({errMsg:"appendFile:fail "+e.message})})}else i.fail({errMsg:`appendFile:fail no such file or directory, open "${e}"`});else i.fail({errMsg:"access:fail parameter error: parameter.data should be String/ArrayBuffer",errno:ERROR$1.PARAMETER_ERROR});else i.fail({errMsg:"access:fail parameter error: parameter.filePath should be String",errno:ERROR$1.PARAMETER_ERROR})}appendFileSync(e,t,o=DEFAULT_ENCODING){if(!checkDataType(e,!0,"string"))throw new Error("access:fail parameter error: parameter.filePath should be String");if(!checkDataType(t,!0,["string","arraybuffer"]))throw new Error("access:fail parameter error: parameter.data should be String/ArrayBuffer");if(!fs.accessSync(e))throw new Error(`appendFile:fail no such file or directory, open "${e}"`);e=fs.openSync(e,fs.OpenMode.READ_WRITE|fs.OpenMode.APPEND),fs.writeSync(e.fd,t)}open({filePath:e,flag:t=DEFAULT_FLAG,success:o,fail:a,complete:r}){let s=new FileCallback({success:o,fail:a,complete:r});if(checkDataType(e,!0,"string")){if(FLAG.includes(t)||(t=DEFAULT_FLAG),Object.keys(modeReflect).includes(t)){if(fs.accessSync(e))return void s.fail({errMsg:"open:fail EXIST: file already exists"});console.debug("[AdvancedAPI] access fail"),t=modeReflect[t]}fs.open(e,getOpenMode(t),(e,t)=>{e?(console.error("[AdvancedAPI] open failed with error message: "+e.message+", error code: "+e.code),s.fail({errMsg:"open:fail "+e.message,errno:ERROR$1.NO_SUCH_FILE_OR_DIRECTORY})):s.success({fd:t.fd.toString(),errMsg:"open:ok"})})}else s.fail({errMsg:"open:fail parameter error: parameter.filePath should be String",errno:ERROR$1.PARAMETER_ERROR})}openSync({filePath:e,flag:t}){if(!checkDataType(e,!0,"string"))throw new Error("openSync:fail parameter error: parameter.filePath should be String");if(FLAG.includes(t)||(t=DEFAULT_FLAG),Object.keys(modeReflect).includes(t)){if(fs.accessSync(e))throw new Error("openSync:fail EXIST: file already exists");console.debug("[AdvancedAPI] access fail"),t=modeReflect[t]}return fs.openSync(e,getOpenMode(t)).fd.toString()}close({fd:e,success:t,fail:o,complete:a}){let r=new FileCallback({success:t,fail:o,complete:a});""!==e&&checkDataType(e,!0,"string")?(e=Number(e),isNaN(e)?r.fail({errMsg:"close:fail bad file descriptor"}):fs.close(e,e=>{e?r.fail({errMsg:"close:fail bad file descriptor"}):r.success({errMsg:"close:ok"})})):r.fail({errMsg:"close:fail invalid fd",errno:ERROR$1.PARAMETER_ERROR})}closeSync({fd:e}){if(""===e||!checkDataType(e,!0,"string"))throw new Error("closeSync:fail invalid fd");if(e=Number(e),isNaN(e))throw new Error("closeSync:fail invalid fd");fs.closeSync(e)}copyFile({srcPath:e,destPath:t,success:o,fail:a,complete:r}){let s=new FileCallback({success:o,fail:a,complete:r});if((o=checkPathExistence("copyFile","srcPath",e)).isValid)if((a=checkPath("copyFile","destPath",t)).isValid)if(fs.statSync(e).isDirectory())s.fail({errMsg:"copyFile: fail illegal operation on a directory, open: "+e});else{if(fs.accessSync(t)){if((r=fs.statSync(t)).isDirectory())t+=obtainFileName(e).fileName;else if(r.isFile()&&e!==t)return void s.fail({errMsg:"copyFile: fail copyFile failed"})}else if(r=obtainUpperPath(t),!fs.accessSync(r.upperPath))return void s.fail({errMsg:"copyFile: fail no such file or directory, open: "+t});fs.copyFile(e,t).then(()=>{s.success({errMsg:"copyFile: ok"})}).catch(e=>{s.fail({errMsg:`copyFile: failed with error message: ${e.message}, error code: `+e.code})})}else s.fail(a.checkMsg);else s.fail(o.checkMsg)}copyFileSync(e,t){var o=checkPathExistenceSync("copyFileSync","srcPath",e);if(!o.isValid)throw new Error(o.errMsg);if(!(o=checkPathSync("copyFileSync","destPath",t)).isValid)throw new Error(o.errMsg);if(fs.statSync(e).isDirectory())throw new Error("copyFileSync: fail illegal operation on a directory: "+e);if(fs.accessSync(t)){if((o=fs.statSync(t)).isDirectory()){var a=t.lastIndexOf("/");let e=t.substring(a);t.endsWith("/")&&(e=t.substring(t.lastIndexOf("/",t.length-2)+1,t.length-1)),t+=e}else if(o.isFile()&&e!==t)throw new Error("copyFileSync: fail copyFile failed")}else if(a=obtainUpperPath(t),!fs.accessSync(a.upperPath))throw new Error("copyFileSync: fail no such file or directory: "+t);try{fs.copyFileSync(e,t)}catch(e){throw new Error("copyFileSync: "+e.message)}}fstat({fd:e,success:t,fail:o,complete:a}){let r=new FileCallback({success:t,fail:o,complete:a});(t=checkFd("fstat",e)).isValid?(e=t.fd,fs.stat(e,(e,t)=>{e?r.fail({errMsg:`fstat: failed with error message: ${e.message}, error code: `+e.code}):(e=getFileTypeMode(t)|t.mode,r.success({stat:{mode:e,size:t.size,lastAccessedTime:t.atime,lastModifiedTime:t.mtime,isDirectory:()=>t.isDirectory(),isFile:()=>t.isFile()},errMsg:"fstat: ok"}))})):r.fail(t.checkMsg)}fstatSync({fd:t}){var e=checkFdSync("fstatSync",t);if(!e.isValid)throw new Error(e.errMsg);t=e.fd;try{let e=fs.statSync(t);return{stat:{mode:getFileTypeMode(e)|e.mode,size:e.size,lastAccessedTime:e.atime,lastModifiedTime:e.mtime,isDirectory:()=>e.isDirectory(),isFile:()=>e.isFile()}}}catch(e){throw new Error("fstatSync: "+e.message)}}ftruncate({fd:e,length:t,success:o,fail:a,complete:r}){let s=new FileCallback({success:o,fail:a,complete:r});(o=checkFd("ftruncate",e)).isValid?(e=o.fd,(!checkDataType(t,!0,"number")||t<0)&&(t=DEFAULT_LENGTH),fs.truncate(e,t).then(()=>{s.success({errMsg:"ftruncate: ok"})}).catch(e=>{s.fail({errMsg:`ftruncate: failed with error message: ${e.message}, error code: `+e.code})})):s.fail(o.checkMsg)}ftruncateSync({fd:e,length:t}){var o=checkFdSync("ftruncateSync",e);if(!o.isValid)throw new Error(o.errMsg);e=o.fd,(!checkDataType(t,!0,"number")||t<0)&&(t=DEFAULT_LENGTH);try{fs.truncateSync(e,t)}catch(e){throw new Error("ftruncateSync: "+e.message)}}mkdir({dirPath:e,recursive:t,success:o,fail:a,complete:r}){let s=new FileCallback({success:o,fail:a,complete:r});checkDataType(t,!1,"boolean")||(t=Boolean(t)),(o=checkPath("mkdir","dirPath",e)).isValid?fs.accessSync(e)?s.fail({errMsg:"mkdir: dirPath already exists: "+e}):t?(mkdirRecursive("",e.split("/")),s.success({errMsg:"mkdir: ok"})):(a=obtainUpperPath(e),fs.accessSync(a.upperPath)?fs.mkdir(e).then(()=>{s.success({errMsg:"mkdir: ok"})}).catch(e=>{s.fail({errMsg:`mkdir: failed with error message: ${e.message}, error code: `+e.code})}):s.fail({errMsg:"mkdir: failed"})):s.fail(o.checkMsg)}mkdirSync(e,t){checkDataType(t,!1,"boolean")||(t=Boolean(t));var o=checkPathSync("mkdirSync","dirPath",e);if(!o.isValid)throw new Error(o.errMsg);if(fs.accessSync(e))throw new Error("mkdirSync: dirPath already exists: "+e);if(!t&&!fs.accessSync(obtainUpperPath(e).upperPath))throw new Error("mkdirSync: fail, recursive is false and upper path does not exist");if(t)try{mkdirRecursive("",e.split("/"))}catch(e){throw new Error("mkdirSync: "+e.message)}else try{fs.mkdirSync(e)}catch(e){throw new Error("mkdirSync: "+e.message)}}read({fd:e,arrayBuffer:r,offset:t=DEFAULT_OFFSET,length:s,position:i,success:o,fail:a,complete:n}){let c=new FileCallback({success:o,fail:a,complete:n});if(!checkDataType(e,!0,"string")||""===e||isNaN(Number(e)))c.fail({errMsg:"read: fail invalid fd"});else if(e=Number(e),checkDataType(r,!0,"arraybuffer"))if((!checkDataType(t,!1,"number")||t<0)&&(t=Number(t),isNaN(t)||t<0)&&(t=DEFAULT_OFFSET),(!checkDataType(s,!1,"number")||s<0)&&(s=Number(s),isNaN(s)||s<0)&&(s=DEFAULT_LENGTH),(o=r.byteLength-t){var t=new Uint8Array(a);new Uint8Array(r).set(t,o),console.debug("[AdvancedAPI] the content of arrayBuffer: %s",String.fromCharCode.apply(null,new Uint8Array(a.slice(0,e)))),c.success({bytesRead:e,arrayBuffer:r,errMsg:"read: ok"})}).catch(e=>{c.fail({errMsg:`read: failed with error message: ${e.message},error code: `+e.code})})}else c.fail({errMsg:"read: fail invalid arrayBuffer: "+r})}readSync({fd:e,arrayBuffer:t,offset:o,length:a,position:r}){if(!checkDataType(e,!0,"string")||""===e||isNaN(Number(e)))throw new Error("readSync:fail invalid fd");if(e=Number(e),!checkDataType(t,!0,"arraybuffer"))throw new Error("readSync: fail invalid arrayBuffer");(!checkDataType(o,!1,"number")||o<0)&&(o=Number(o),isNaN(o)||o<0)&&(o=DEFAULT_OFFSET),(!checkDataType(a,!1,"number")||a<0)&&(a=Number(a),isNaN(a)||a<0)&&(a=DEFAULT_LENGTH);var s=t.byteLength-o;if(s{r.success({files:e,errMsg:"readdir: ok"})}).catch(e=>{r.fail({errMsg:`readdir: failed with error message: ${e.message}, error code: `+e.code})}):r.fail(t.checkMsg)}readdirSync(e){var t=checkPathExistence("readdirSync","dirPath",e);if(!t.isValid)throw new Error(t.errMsg);if(fs.statSync(e).isFile())throw new Error("readdirSync: fail not a directory: ${dirPath}");try{return{files:fs.listFileSync(e)}}catch(e){throw new Error("readdirSync: "+e.message)}}readFile({filePath:o,encoding:a,position:r=DEFAULT_POSITION,length:s,success:e,fail:t,complete:i}){o=isSandboxPath(o)?switchInternalToHapSandBox(o):o;let n=new FileCallback({success:e,fail:t,complete:i});if((e=checkPathExistence("readFile","filePath",o)).isValid)if((t=fs.statSync(o)).isDirectory())n.fail({errMsg:"readFile:fail not absolute path: "+o});else if((i=checkEncoding("readFile",a)).isValid)if(t=t.size,s=null==s?t:s,checkDataType(r,!1,"number"))if(checkDataType(s,!1,"number"))if(r<0||t{var e=a?buffer.from(t).toString(a):t;n.success({data:e,errMsg:"readFile:ok"})}).catch(e=>{n.fail({errMsg:`readFile:fail error message: ${e.message}, error code: `+e.code})}).finally(()=>{fs.closeSync(e)})}else n.fail({errMsg:"readFile:fail invalid length: "+s});else n.fail({errMsg:"readFile:fail invalid position: "+r});else n.fail({errMsg:i.checkMsg});else n.fail(e.checkMsg)}readFileSync(e,t,o=DEFAULT_POSITION,a){var r=checkPathExistenceSync("readFileSync","filePath",e=isSandboxPath(e)?switchInternalToHapSandBox(e):e);if(!r.isValid)throw new Error(r.errMsg);if((r=fs.statSync(e)).isDirectory())throw new Error("readFileSync:fail illegal operation on a directory, open: "+e);var s=checkEncoding("readFile",t);if(!s.isValid)throw new Error(s.checkMsg);if(s=r.size,a=null==a?s:a,!checkDataType(o,!1,"number"))throw new Error("readFileSync:fail invalid position: "+o);if(!checkDataType(a,!1,"number"))throw new Error("readFileSync:fail invalid length: "+a);if(o<0||s{s.success({errMsg:"rename: ok"})}).catch(e=>{s.fail({errMsg:`rename: failedwith error message: ${e.message}, error code: `+e.code})})}else s.fail(a.checkMsg);else s.fail(o.checkMsg)}renameSync(e,t){var o=checkPathExistenceSync("renameSync","oldPath",e);if(!o.isValid)throw new Error(o.errMsg);if(!(o=checkPathSync("renameSync","newPath",t)).isValid)throw new Error(o.errMsg);if(!(o=fs.accessSync(t))&&!fs.accessSync(obtainUpperPath(t).upperPath))throw new Error("renameSync: fail no such file or directory, open: "+t);if(o&&e!==t)throw new Error("renameSync: fail");try{fs.renameSync(e,t)}catch(e){throw new Error("renameSync: "+e.message)}}rmdir({dirPath:e,recursive:t,success:o,fail:a,complete:r}){let s=new FileCallback({success:o,fail:a,complete:r});checkDataType(t,!1,"boolean")||(t=Boolean(t)),(o=checkPathExistence("rmdir","dirPath",e)).isValid?fs.statSync(e).isDirectory()?!t&&fs.listFileSync(e).length?s.fail({errMsg:"rmdir: fail directory not empty"}):fs.rmdir(e).then(()=>{console.debug("[AdvanceAPI] rmdir succeed"),s.success({errMsg:"rmdir: ok"})}).catch(e=>{console.error(`[AdvanceAPI] rmdir failed with error message: ${e.message}, error code: `+e.code),s.fail({errMsg:"rmdir: failed"})}):s.fail({errMsg:"rmdir: fail no such directory, open: "+e}):s.fail(o.checkMsg)}rmdirSync(e,t){checkDataType(t,!1,"boolean")||(t=Boolean(t));var o=checkPathExistenceSync("rmdirSync","dirPath",e);if(!o.isValid)throw new Error(o.errMsg);if(!fs.statSync(e).isDirectory())throw new Error("rmdirSync: fail no such directory, open: "+e);if(!t&&0{console.debug("[AdvancedAPI] truncate: success, the read length is: %d",t),s.success({errMsg:"truncate: ok"})}).catch(e=>{console.error(`[AdvancedAPI] truncate: fail with error message: ${e.message}, error code: `+e.code),s.fail({errMsg:`truncate: failed with error message: ${e.message}, error code: `+e.code})})):s.fail(o.checkMsg)}truncateSync({filePath:e,length:t}){var o=checkPathExistenceSync("truncateSync","filePath",e);if(!o.isValid)throw new Error(o.errMsg);if(fs.statSync(e).isDirectory())throw new Error("truncateSync: fail, illegal operation on a directory, open: "+e);(!checkDataType(t,!0,"number")||t<0)&&(t=DEFAULT_LENGTH);try{fs.truncateSync(e,t)}catch(e){throw new Error("truncateSync: "+e.message)}}getFileInfo({filePath:e,success:t,fail:o,complete:a}){t=new FileCallback({success:t,fail:o,complete:a}),(e=isSandboxPath(e)?switchInternalToHapSandBox(e):e)&&checkDataType(e,!0,"string")?fs.accessSync(e)?(o=fs.statSync(e),t.success({size:o.size,errMsg:"getFileInfo:ok "})):t.fail({errMsg:"getFileInfo: fail no such file or directory : "+e}):t.fail({errMsg:"getFileInfo:fail invalid filePath "})}}class ASFile{constructor(){this.DIGESTALGORITHM_VALUES=["MD5","SHA1"],this.saveFileDir=context.filesDir+"/saveFiles",this.fileSystemManager=new FileSystemManager,this.init()}init(){try{FileioBase.ohosMkdirSync(this.saveFileDir)}catch(e){console.debug("[AdvancedAPI] %s 已存在",this.saveFileDir)}}saveFile(e){return new Promise(async(s,i)=>{var n=e.tempFilePath;if(n)try{let e=n.substr(n.lastIndexOf("/")),t=e&&e.split(".").pop(),o=(new Date).getTime(),a=(t&&(o+="."+t),getFdFromUriOrSandBoxPath(isSandboxPath(n)?fileuri.getUriFromPath(switchInternalToHapSandBox(n)):n)),r=this.saveFileDir+"/"+o;FileioBase.ohosCopy(a,r).then(()=>{console.debug("[AdvancedAPI] saveFile succeed"),s({savedFilePath:r})}).catch(e=>{console.error("[AdvancedAPI] saveFile failed with error message: "+e.message+", error code: "+e.code),i([e.message,ErrorCode$1.IO_ERROR])})}catch(e){console.error("[AdvancedAPI] tempFilePath does not exist"),i(["tempFilePath does not exist",ErrorCode$1.PARAMETER_ERROR])}else console.error("[AdvancedAPI] invalid tempFilePath."),i(["tempFilePath is required.",ErrorCode$1.PARAMETER_ERROR])})}getSavedFileList(){return new Promise((e,t)=>{var o=[],a=FileioBase.ohosOpendirSync(this.saveFileDir).ohosReadsync();for(let e=0;e{var o=a.filePath;o?(o=getFdFromUriOrSandBoxPath(isSandboxPath(o)?fileuri.getUriFromPath(switchInternalToHapSandBox(o)):o),e({createTime:(e=FileioBase.ohosStatSync(o)).mtime,size:e.size,errMsg:"getSavedFileInfo:ok"})):(console.error("[AdvancedAPI] filePath is required."),t(["filePath is required",ErrorCode$1.PARAMETER_ERROR]))})}removeSavedFile(r){return new Promise((e,t)=>{var o=r.filePath;if(o)try{var a=isSandboxPath(o)?switchInternalToHapSandBox(o):o;FileioBase.ohosUnlinkSync(a),e("success")}catch(e){t(["removeSavedFile is fail",ErrorCode$1.IO_ERROR])}else console.error("[AdvancedAPI] filePath is required."),t(["filePath is required",ErrorCode$1.PARAMETER_ERROR])})}getFileInfo(t){return new Promise((r,e)=>{let s=t.filePath,{digestAlgorithm:i="MD5"}=t;if(s){"string"==typeof i&&(i=i.toUpperCase()),this.DIGESTALGORITHM_VALUES.includes(i)||(console.error("[AdvancedAPI] digestAlgorithm is invalid."),i="MD5");try{let e=isSandboxPath(s)?fileuri.getUriFromPath(switchInternalToHapSandBox(s)):s,t=FileioBase.ohosOpenSync(e,2).fd,o=FileioBase.ohosStatSync(t),a=new ArrayBuffer(o.size);FileioBase.ohosReadSync(t,a),SecurityBase.rsa(i,{data:new Uint8Array(a)}).then(e=>{var t=new util.TextDecoder("utf-8",{ignoreBOM:!0});r({size:o.size,digest:t.decodeWithStream(e,{stream:!1})})})}catch(s){console.error("[AdvancedAPI] getFileInfo fail err = "+JSON.stringify(s)),e(["getFileInfo is fail",ErrorCode$1.IO_ERROR])}}else console.error("[AdvancedAPI] filePath is required."),e(["filePath is required",ErrorCode$1.PARAMETER_ERROR])})}openDocument(a){return new Promise((e,t)=>{var{showMenu:o=!1}=a;o&&console.error("[AdvancedAPI] showMenu do not support.")})}getFileSystemManager(){return this.fileSystemManager}}let name=settings.display.SCREEN_BRIGHTNESS_STATUS;class BrightnessBase{static ohoGetValue(){try{var e=settings.getValueSync(context,name,"1");return console.log("[AdvancedAPI] success to get brightness. value:"+e),Math.round(2.55*e),e}catch(e){console.log("[QAFAPI] Failed to get brightness. Cause:"+JSON.stringify(e))}}}_dec$2=jsMethod({alias:"getValue",common:!1,callback:!0}),_dec2$2=jsMethod({alias:"setValue",common:!1,callback:!0}),_dec3$1=jsMethod({alias:"setKeepScreenOn",common:!1,callback:!0}),_applyDecoratedDescriptor((_class$2=class{getValue(){return new Promise((o,t)=>{try{window.getLastWindow(context).then(e=>{let t=e.getWindowProperties().brightness;(!t||t<0)&&(t=Number(BrightnessBase.ohoGetValue())/255),e={value:Math.round(255*t)},console.debug("[QAFAPI] getValue success, brightness = "+JSON.stringify(e)),o([e])})}catch(e){t([["Failed to get brightness"]]),console.error("Failed to obtain the window properties. Cause: "+JSON.stringify(e))}})}setValue(e){return new Promise((o,a)=>{var r,s=e.value;if(s||0===s)if(isNumber(r=s)){let e=Math.floor(r),t=(e<0?e=1:255{e.setWindowBrightness(t,e=>{e.code?(a([["setWindowBrightness fail"]]),console.error("[QAFAPI] Failed to set the brightness. Cause: "+JSON.stringify(e))):(o("successed to set"),console.info("[QAFAPI] Succeeded in setting the brightness."))})})}catch(s){console.error("[QAFAPI] Failed to set setting of brightness. Cause:"+JSON.stringify(s)),a([["setWindowBrightness fail"]])}}else a([["inalid param",ErrorCode$1.PARAMETER_ERROR]]);else a([["inalid param",ErrorCode$1.PARAMETER_ERROR]])})}setKeepScreenOn(e){return new Promise((o,a)=>{if(e&&""!==e.keepScreenOn&&null!==e.keepScreenOn){let t=e.keepScreenOn;if("boolean"==typeof t)try{window.getLastWindow(context).then(e=>{e.setWindowKeepScreenOn(t,e=>{e.code?(console.error("[QAFAPI] Failed to set the screen to be always on. Cause: "+JSON.stringify(e)),a([["handling failed"]])):(o(["handling success"]),console.info("[QAFAPI] Succeeded in setting the screen to be always on."))})})}catch(e){console.error("[QAFAPI] Failed to set the screen to be always on. exception: "+JSON.stringify(e)),a([["handling failed"]])}else a([["inalid param",ErrorCode$1.PARAMETER_ERROR]])}else a([["inalid param",ErrorCode$1.PARAMETER_ERROR]])})}}).prototype,"getValue",[_dec$2],Object.getOwnPropertyDescriptor(_class$2.prototype,"getValue"),_class$2.prototype),_applyDecoratedDescriptor(_class$2.prototype,"setValue",[_dec2$2],Object.getOwnPropertyDescriptor(_class$2.prototype,"setValue"),_class$2.prototype),_applyDecoratedDescriptor(_class$2.prototype,"setKeepScreenOn",[_dec3$1],Object.getOwnPropertyDescriptor(_class$2.prototype,"setKeepScreenOn"),_class$2.prototype);let BrightnessBaseModule=_class$2;class ASBrightness extends BrightnessBaseModule{setScreenBrightness(e){if(console.info("[AdvancedAPI] params = "+JSON.stringify(e)),e&&void 0!==e.value&&"number"==typeof e.value){var t=e.value;if(t<=1&&0<=t)return this.setValue({value:Math.round(255*e.value)})}return new Promise((e,t)=>{t(["param is invalid.",ErrorCode$1.PARAMETER_ERROR])})}getScreenBrightness(){return this.getValue()}asSetKeepScreenOn(e){return this.setKeepScreenOn(e)}}class ASInterceptor{constructor(){this.apiLists={},this.globals=[]}checkApiName(e){return"addInterceptor"!==e&&"removeInterceptor"!==e}invoke(e,t){this.globals.forEach(e=>{"function"==typeof(e=e.invoke)&&e(...t)}),(this.apiLists[e]||[]).forEach(e=>{"function"==typeof(e=e.invoke)&&e(...t)})}success(e,o){let a=[];if(this.globals.forEach(e=>{"function"==typeof(e=e.success)&&a.push(e)}),(this.apiLists[e]||[]).forEach(e=>{"function"==typeof(e=e.success)&&a.push(e)}),a.length){let t=o&&JSON.parse(JSON.stringify(o));return a.forEach(e=>{e(...t)}),t}}fail(e,o){let a=[];if(this.globals.forEach(e=>{"function"==typeof(e=e.fail)&&a.push(e)}),(this.apiLists[e]||[]).forEach(e=>{"function"==typeof(e=e.fail)&&a.push(e)}),a.length){let t=o&&JSON.parse(JSON.stringify(o));return a.forEach(e=>{e(...t)}),t}}complete(e,o){let a=[];if(this.globals.forEach(e=>{"function"==typeof(e=e.complete)&&a.push(e)}),(this.apiLists[e]||[]).forEach(e=>{"function"==typeof(e=e.complete)&&a.push(e)}),a.length){let t=o&&JSON.parse(JSON.stringify(o));return a.forEach(e=>{e(...t)}),t}}returnValue(e,t){this.globals.forEach(e=>{"function"==typeof(e=e.returnValue)&&e(t)}),(this.apiLists[e]||[]).forEach(e=>{"function"==typeof(e=e.returnValue)&&e(t)})}}let SCAN_TYPE_AS_TO_HM={barCode:null==scanCore?void 0:scanCore.ScanType.ONE_D_CODE,qrCode:null==scanCore?void 0:scanCore.ScanType.TWO_D_CODE,datamatrix:null==scanCore?void 0:scanCore.ScanType.DATAMATRIX_CODE,pdf417:null==scanCore?void 0:scanCore.ScanType.PDF417_CODE};class ASScan{scanCode(i={}){return new Promise((t,o)=>{var{onlyFromCamera:e=!1,hideAlbum:a=!1,scanType:r=[]}=i,s=[];for(let e=0;e{t({result:e.originalValue,scanType:this.scanTypeHmToAs(e.scanType),rawData:gBase64.btoa(e.originalValue),charSet:"utf-8"})}).catch(e=>{o(["scanCode fail!",ErrorCode$1.COMMON_ERROR])})}catch(e){o(["scanCode fail!",ErrorCode$1.COMMON_ERROR])}}else o(["Parameter hideAlbum invalid!",ErrorCode$1.PARAMETER_ERROR]);else o(["Parameter onlyFromCamera invalid!",ErrorCode$1.PARAMETER_ERROR])})}scanTypeHmToAs(e){let t="UNKNOWN";switch(e){case scanCore.ScanType.DATAMATRIX_CODE:t="DATA_MATRIX";break;case scanCore.ScanType.PDF417_CODE:t="PDF_417";break;case scanCore.ScanType.AZTEC_CODE:t="AZTEC";break;case scanCore.ScanType.CODABAR_CODE:t="CODABAR";break;case scanCore.ScanType.CODE39_CODE:t="CODE_39";break;case scanCore.ScanType.CODE93_CODE:t="CODE_93";break;case scanCore.ScanType.CODE128_CODE:t="CODE_128";break;case scanCore.ScanType.EAN8_CODE:t="EAN_8";break;case scanCore.ScanType.EAN13_CODE:t="EAN_13";break;case scanCore.ScanType.ITF14_CODE:t="ITF";break;case scanCore.ScanType.QR_CODE:t="QR_CODE";break;case scanCore.ScanType.UPC_A_CODE:t="UPC_A";break;case scanCore.ScanType.UPC_E_CODE:t="UPC_E";break;case scanCore.ScanType.MULTIFUNCTIONAL_CODE:t="MULTIFUNCTIONAL";break;case scanCore.ScanType.ONE_D_CODE:t="CODABAR";break;case scanCore.ScanType.TWO_D_CODE:t="QR_CODE"}return t}}let asModulesMap=new Map,moduleInstance=(asModulesMap.set("ASDevice",ASDevice),asModulesMap.set("ASLocation",ASLocation),asModulesMap.set("ASPhone",ASPhone),asModulesMap.set("ASRequest",ASRequest),asModulesMap.set("ASRouter",ASRouter),asModulesMap.set("ASBluetooth",ASBluetooth),asModulesMap.set("ASWifi",ASWifi),asModulesMap.set("ASAuthentication",ASAuthentication),asModulesMap.set("ASAccelerometer",ASAccelerometer),asModulesMap.set("ASCompass",ASCompass),asModulesMap.set("ASGyroscope",ASGyroscope),asModulesMap.set("ASContact",ASContact),asModulesMap.set("ASVibrator",ASVibrator),asModulesMap.set("ASCapture",ASCapture),asModulesMap.set("ASKeyboard",ASKeyboard),asModulesMap.set("ASImage",ASImage),asModulesMap.set("ASBrightness",ASBrightness),asModulesMap.set("ASFile",ASFile),asModulesMap.set("ASAudio",ASAudio),asModulesMap.set("ASBGAudio",ASBGAudio),asModulesMap.set("ASVideo",ASViedo),asModulesMap.set("ASInterceptor",ASInterceptor),asModulesMap.set("ASScan",ASScan),{});function requireAPI$1(e){var t;return moduleInstance[e]||(console.debug("[AdvancedAPI] create %s",e),t=asModulesMap.get(e),moduleInstance[e]=new t),moduleInstance[e]}class CallbackManager{constructor(e){this.lastCallbackId=0,this.callbacks=[]}add(e){return this.lastCallbackId++,(this.callbacks[this.lastCallbackId]=e).__callbackId=this.lastCallbackId,this.lastCallbackId}consume(e,t,o){var a=this.callbacks[e];return void 0===o||!1===o?this.callbacks[e]=void 0:a.isKeepAlive=!0,"function"==typeof a?a(t):new Error(`invalid callback id "${e}"`)}close(){this.callbacks=this.callbacks.map(e=>{})}}let callbackManager=new CallbackManager;function interceptCallback(e,a,t=!0,o=!0){if(!(t||0!==e.length&&o))return{args:e};let r=e[0],s={},i=!1;if("object"==typeof r&&"[object object]"===Object.prototype.toString.call(r).toLowerCase()&&1===e.length)for(var n in r){var c=r[n];"function"==typeof c?s[n]=c:i=!0}else i=!0;"function"==typeof r&&(t=!1,r.isConnected?r.cb&&(e[0]=r.cb.id):(((o=e=>{r.apply(null,e.arguments)}).originFn=r).cb=o,e[0]=o));let l;var d,o=Object.keys(s).length;if(t&&o<=0){class h{constructor(){this.promise=new Promise((e,t)=>{this.reject=t,this.resolve=e})}}l=new h}return(0{let t=s[e.method];advancedResult(a,e);var o=triggerMethodIntercept(a,e.method,e.arguments)||e.arguments,{ignoreComplete:o=!1}=(void 0!==t&&t.apply(null,o),e);o||(o=triggerMethodIntercept(a,"complete",e.arguments)||e.arguments,void 0!==(t=s.complete)&&t.apply(null,o)),l&&(o=(o=e.arguments)&&0normalize(e))),r&&r.cb&&(r.isConnected=!0),{args:e,promise:l,needPromise:t}}function normalize(e){var t;return"function"==typeof e?(t=callbackManager.add(e),e.id=t):e}function advancedResult(e,t){var o;"success"===t.method?(t.arguments[0]&&"object"==typeof t.arguments[0]||(t.arguments[0]={}),void 0===(o=t.arguments[0]).errMsg&&(o.errMsg=e+":ok"),void 0===o.errCode&&(o.errCode=0)):"fail"===t.method&&(o=t.arguments||[],t.arguments=[{moduleName:""+e,errMsg:e+":fail:"+o.shift(),errCode:o.shift(),grantStatus:o.shift(),dialogShownResults:o.shift()}])}function triggerMethodIntercept(e,t,o){var a=requireAPI("ASInterceptor");if("function"==typeof(t=a[t]))return t.call(a,e,o)}class JSCallback{constructor(e){this.id=e.id,this._valid=!0}invoke(e){this._valid?callbackManager.consume(this.id,e,e.ifKeepAlive):console.error(`[AdvancedAPI] callback ${this.id} had be destroyed.`)}invokeAndKeepAlive(e){this._valid?callbackManager.consume(this.id,e,!0):console.error(`[AdvancedAPI] callback ${this.id} had be destroyed.`)}destroy(){this.id=void 0,this._valid=!1}}let jsCallbackMap=new Map;function getSystemInfoSync(){return console.debug("[AdvancedAPI] start getSystemInfoSync"),requireAPI("ASDevice").getSystemInfoSync()}function getDeviceInfo(...e){return console.debug("[AdvancedAPI] start getDeviceInfo"),e.pop(),e=requireAPI("ASDevice"),console.debug("[AdvancedAPI] device.getInfo"),e=e.getDeviceInfo()}function getWindowInfo(...e){return console.debug("[AdvancedAPI] start getWindowInfo"),e.pop(),requireAPI("ASDevice").getWindowInfo()}function getAppBaseInfo(...e){return console.debug("[AdvancedAPI] start getAppBaseInfo"),e.pop(),requireAPI("ASDevice").getAppBaseInfo()}function getAppAuthorizeSetting(...e){return console.debug("[AdvancedAPI] start getAppAuthorizeSetting"),e.pop(),requireAPI("ASDevice").getAppAuthorizeSetting()}function getSystemSetting(...e){return console.debug("[AdvancedAPI] start getSystemSetting"),e.pop(),e=requireAPI("ASDevice"),console.debug("[AdvancedAPI] device.getSystemSetting"),e=e.getSystemSetting()}function openAppAuthorizeSetting(...e){console.debug("[AdvancedAPI] start getSystemSetting");var e=e.pop(),t=requireAPI("ASDevice");try{t.openAppAuthorizeSetting(),e.invoke(Result.success("success"))}catch(t){e.invoke(Result.fail(["fail"],201))}}function navigateTo(...e){let t=e.pop();e=e.pop()||{},requireAPI("ASRouter").navigateTo(e).then(e=>{t.invoke(Result.success(e))},e=>{t.invoke(Result.fail(e))})}function redirectTo(...e){let t=e.pop();e=e.pop()||{},requireAPI("ASRouter").redirectTo(e).then(e=>{t.invoke(Result.success(e))},e=>{t.invoke(Result.fail(e))})}function navigateBack(...e){let t=e.pop();e=e.pop()||{},requireAPI("ASRouter").navigateBack(e).then(e=>{t.invoke(Result.success(e))},e=>{t.invoke(Result.fail(e))})}function getLocation(...e){console.debug("[AdvancedAPI] start getLocation");let o=e.pop();var e=e.pop(),t=requireAPI("ASLocation");console.debug("[AdvancedAPI] geolocation.getLocation"),t.getLocation(e).then(e=>{console.debug("[AdvancedAPI] geolocation.getLocation success"),o.invoke(Result.success(e))},(e,t)=>{console.debug("[AdvancedAPI] geolocation.getLocation fail"),o.invoke(Result.fail(e))})}function onLocationChange(...e){console.debug("[AdvancedAPI] start onLocationChange"),e=e.pop(),requireAPI("ASLocation").onLocationChange(e)}function offLocationChange(...e){console.debug("[AdvancedAPI] start offLocationChange");let t=e.pop();(e=requireAPI("ASLocation")).offLocationChange(t),e.getLocation({timeout:5e3,coordType:"wgs86"}).then(e=>{console.debug("[AdvancedAPI] geolocation.offLocationChange callback"),t.invokeAndKeepAlive(Result.success(e))},e=>{t.invokeAndKeepAlive(Result.fail([e[0][0],e[0][1]]))})}function onLocationChangeError(...e){console.debug("[AdvancedAPI] start onLocationChangeError");let t=e.pop();requireAPI("ASLocation").onLocationChangeError(e=>{console.debug("[AdvancedAPI] geolocation.onLocationChange success"),t.invokeAndKeepAlive(Result.callback(e))})}function offLocationChangeError(...e){console.debug("[AdvancedAPI] start offLocationChangeError"),e=e.pop(),requireAPI("ASLocation").offLocationChangeError(),e.invoke(Result.success())}function startLocationUpdate(...e){console.debug("[AdvancedAPI] start startLocationUpdate");let o=e.pop();requireAPI("ASLocation").startLocationUpdate().then(e=>{console.debug("[AdvancedAPI] geolocation.startLocationUpdate success"),o.invoke(Result.success(e))},(e,t)=>{console.debug("[AdvancedAPI] geolocation.startLocationUpdate fail"),o.invoke(Result.fail([e[0][0],e[0][1]]))})}function startLocationUpdateBackground(...e){console.debug("[AdvancedAPI] start startLocationUpdateBackground");let o=e.pop();requireAPI("ASLocation").startLocationUpdateBackground().then(e=>{console.debug("[AdvancedAPI] geolocation.startLocationUpdateBackground success"),o.invoke(Result.success(e))},(e,t)=>{console.debug("[AdvancedAPI] geolocation.startLocationUpdateBackground fail"),o.invoke(Result.fail([e[0][0],e[0][1]]))})}function stopLocationUpdate(...e){console.debug("[AdvancedAPI] start stopLocationUpdate");let o=e.pop();requireAPI("ASLocation").stopLocationUpdate(o).then(e=>{console.debug("[AdvancedAPI] geolocation.stopLocationUpdate success"),o.invoke(Result.success(e))},(e,t)=>{console.debug("[AdvancedAPI] geolocation.stopLocationUpdate fail"),o.invoke(Result.fail([e[0][0],e[0][1]]))})}function makePhoneCall(...e){let t=e.pop();e=e.pop(),requireAPI("ASPhone").makePhoneCall(e).then(()=>{t.invoke(Result.success())},e=>{console.error("[AdvancedAPI] start makePhoneCall fail"),t.invoke(Result.fail([e,-1]))})}function request(...e){var t=e.pop(),e=e.pop(),o=requireAPI("ASRequest"),o=(console.debug("[AdvancedAPI] request"),o.request(e));if(!e||e.success||e.fail||e.complete)return e||t.invoke(Result.fail(["illegal params",-1])),o;t.invoke(Result.success(o))}function uploadFile(...e){var t=e.pop(),e=e.pop(),o=requireAPI("ASRequest"),o=(console.debug("[AdvancedAPI] uploadFile"),o.uploadFile(e));if(!e||e.success||e.fail||e.complete)return e||t.invoke(Result.fail(["illegal params",-1])),o;t.invoke(Result.success(o))}function downloadFile(...e){var t=e.pop(),e=e.pop(),o=requireAPI("ASRequest"),o=(console.debug("[AdvancedAPI] downloadFile"),o.downloadFile(e));if(!e||e.success||e.fail||e.complete)return e||t.invoke(Result.fail(["illegal params",-1])),o;t.invoke(Result.success(o))}function openBluetoothAdapter(...e){let t=e.pop();requireAPI("ASBluetooth").openBluetoothAdapter().then(e=>{t.invoke(Result.success(e))},e=>{t.invoke(Result.fail(...e))})}function closeBluetoothAdapter(...e){let t=e.pop();requireAPI("ASBluetooth").closeBluetoothAdapter().then(e=>{t.invoke(Result.success(e))},e=>{t.invoke(Result.fail(...e))})}function startBluetoothDevicesDiscovery(...e){let t=e.pop();e=e.pop(),requireAPI("ASBluetooth").startBluetoothDevicesDiscovery(e).then(e=>{t.invoke(Result.success(e))},e=>{t.invoke(Result.fail(...e))})}function stopBluetoothDevicesDiscovery(...e){let t=e.pop();requireAPI("ASBluetooth").stopBluetoothDevicesDiscovery().then(e=>{t.invoke(Result.success(e))},e=>{t.invoke(Result.fail(...e))})}function onBluetoothDeviceFound(...e){e=e.pop(),requireAPI("ASBluetooth").onBluetoothDeviceFound(e)}function offBluetoothDeviceFound(...e){e=e.pop(),requireAPI("ASBluetooth").offBluetoothDeviceFound(e)}function onBluetoothAdapterStateChange(...e){e=e.pop(),requireAPI("ASBluetooth").onBluetoothAdapterStateChange(e)}function offBluetoothAdapterStateChange(...e){e=e.pop(),requireAPI("ASBluetooth").offBluetoothAdapterStateChange(e)}function getBluetoothDevices(...e){let t=e.pop();requireAPI("ASBluetooth").getBluetoothDevices().then(e=>{e=e&&e[0]&&e[0][0]||{},t.invoke(Result.success(e))},e=>{console.info("[AdvancedAPI] getBluetoothDevices fail"+JSON.stringify(e)),t.invoke(Result.fail(...e))})}function getConnectedBluetoothDevices(...e){let t=e.pop();e=e.pop(),requireAPI("ASBluetooth").getConnectedBluetoothDevices(e).then(e=>{console.info("[AdvancedAPI] getConnectedBluetoothDevices success"+JSON.stringify(e)),t.invoke(Result.success(e))},e=>{console.info("[AdvancedAPI] getConnectedBluetoothDevices fail"+JSON.stringify(e)),t.invoke(Result.fail(...e))})}function getBluetoothAdapterState(...e){let t=e.pop();requireAPI("ASBluetooth").getBluetoothAdapterState().then(e=>{t.invoke(Result.success(e))},e=>{t.invoke(Result.fail(...e))})}function setBLEMTU(...e){let t=e.pop();e=e.pop(),requireAPI("ASBluetooth").asSetBLEMTU(e).then(e=>{t.invoke(Result.success(e))},e=>{t.invoke(Result.fail(...e))})}function writeBLECharacteristicValue(...e){let t=e.pop();e=e.pop(),requireAPI("ASBluetooth").asWriteBLECharacteristicValue(e).then(e=>{t.invoke(Result.success(e))},e=>{t.invoke(Result.fail(...e))})}function readBLECharacteristicValue(...e){let t=e.pop();e=e.pop(),requireAPI("ASBluetooth").asReadBLECharacteristicValue(e).then(e=>{t.invoke(Result.success(e))},e=>{t.invoke(Result.fail(...e))})}function onBLEConnectionStateChange(...e){e=e.pop(),requireAPI("ASBluetooth").asOnBLEConnectionStateChange(e)}function offBLEConnectionStateChange(...e){e=e.pop(),requireAPI("ASBluetooth").asOffBLEConnectionStateChange(e)}function onBLECharacteristicValueChange(...e){e=e.pop(),requireAPI("ASBluetooth").asOnBLECharacteristicValueChange(e)}function offBLECharacteristicValueChange(...e){e=e.pop(),requireAPI("ASBluetooth").asOffBLECharacteristicValueChange(e)}function notifyBLECharacteristicValueChange(...e){let t=e.pop();e=e.pop(),requireAPI("ASBluetooth").asNotifyBLECharacteristicValueChange(e).then(e=>{t.invoke(Result.success(e))},e=>{t.invoke(Result.fail(...e))})}function getBLEDeviceServices(...e){let t=e.pop();e=e.pop(),requireAPI("ASBluetooth").asGetBLEDeviceServices(e).then(e=>{t.invoke(Result.success(e[0][0]))},e=>{t.invoke(Result.fail(...e))})}function getBLEDeviceRSSI(...e){let t=e.pop();e=e.pop(),requireAPI("ASBluetooth").asGetBLEDeviceRSSI(e).then(e=>{t.invoke(Result.success(e))},e=>{t.invoke(Result.fail(...e))})}function getBLEDeviceCharacteristics(...e){console.debug("[AdvancedAPI] enter getBLEDeviceCharacteristics");let t=e.pop();e=e.pop(),requireAPI("ASBluetooth").asGetBLEDeviceCharacteristics(e).then(e=>{t.invoke(Result.success(e[0]))},e=>{t.invoke(Result.fail(...e))})}function createBLEConnection(...e){let t=e.pop();var{deviceId:e,timeout:o}=e.pop()||{};requireAPI("ASBluetooth").asCreateBLEConnection({deviceId:e,timeout:o}).then(e=>{t.invoke(Result.success(e))},e=>{t.invoke(Result.fail(...e))})}function closeBLEConnection(...e){let t=e.pop();e=e.pop(),requireAPI("ASBluetooth").asCloseBLEConnection({deviceId:e?e.deviceId:void 0}).then(e=>{t.invoke(Result.success(e))},e=>{t.invoke(Result.fail(...e))})}function startWifi(...e){let t=e.pop();requireAPI("ASWifi").startWifi().then(e=>{t.invoke(Result.success(e))},e=>{t.invoke(Result.fail(e))})}function stopWifi(...e){let t=e.pop();requireAPI("ASWifi").stopWifi().then(e=>{t.invoke(Result.success(e))},e=>{t.invoke(Result.fail(e))})}function getConnectedWifi(...e){let t=e.pop();e=e.pop(),requireAPI("ASWifi").getConnectedWifi(e).then(e=>{t.invoke(Result.success(e))},e=>{t.invoke(Result.fail(e))})}function getWifiList(...e){let t=e.pop();e=e.pop(),requireAPI("ASWifi").getWifiList(e).then(e=>{t.invoke(Result.success(e))},e=>{t.invoke(Result.fail(e))})}function onGetWifiList(...e){e=e.pop(),requireAPI("ASWifi").onGetWifiList(e)}function offGetWifiList(...e){e=e.pop(),requireAPI("ASWifi").offGetWifiList(e)}function connectWifi(...e){let t=e.pop();e=e.pop(),requireAPI("ASWifi").connectWifi(e).then(e=>{t.invoke(Result.success(e))},e=>{t.invoke(Result.fail(e))})}function onWifiConnected(...e){e=e.pop(),requireAPI("ASWifi").onWifiConnected(e)}function offWifiConnected(...e){e=e.pop(),requireAPI("ASWifi").offWifiConnected(e)}function onWifiConnectedWithPartialInfo(...e){e=e.pop(),requireAPI("ASWifi").onWifiConnectedWithPartialInfo(e)}function offWifiConnectedWithPartialInfo(...e){e=e.pop(),requireAPI("ASWifi").offWifiConnectedWithPartialInfo(e)}function startSoterAuthentication(...e){console.debug("[AdvancedAPI] start startSoterAuthentication");let t=e.pop();e=e.pop(),console.debug("[AdvancedAPI] params = %s",JSON.stringify(e)),requireAPI("ASAuthentication").start(e).then(e=>{t.invoke(Result.success(e))},e=>{t.invoke(Result.fail(e))})}function checkIsSupportSoterAuthentication(...e){console.debug("[AdvancedAPI] start checkIsSupportSoterAuthentication");let t=e.pop();requireAPI("ASAuthentication").getSupportedType().then(e=>{t.invoke(Result.success(e))},e=>{t.invoke(Result.fail(e))})}function checkIsSoterEnrolledInDevice(...e){console.debug("[AdvancedAPI] start checkIsSoterEnrolledInDevice");let t=e.pop();e=e.pop(),console.debug("[AdvancedAPI] params = %s",JSON.stringify(e)),requireAPI("ASAuthentication").isEnrolled(e).then(e=>{t.invoke(Result.success(e))},e=>{t.invoke(Result.fail(e))})}function onAccelerometerChange(...e){console.debug("[AdvancedAPI] start onAccelerometerChange"),e=e.pop(),requireAPI("ASAccelerometer").onAccelerometerChange(e).then(e=>{console.debug("[AdvancedAPI] onAccelerometerChange success")},(e,t)=>{console.debug("[AdvancedAPI] onAccelerometerChange fail errMsg = %o, code = %d",e,t)})}function offAccelerometerChange(...e){console.debug("[AdvancedAPI] start offAccelerometerChange"),e=e.pop(),requireAPI("ASAccelerometer").offAccelerometerChange(e).then(e=>{console.debug("[AdvancedAPI] offAccelerometerChange success")},(e,t)=>{console.debug("[AdvancedAPI] offAccelerometerChange fail errMsg = %o, code = %d",e,t)})}function startAccelerometer(...e){console.debug("[AdvancedAPI] start startAccelerometer");let o=e.pop();requireAPI("ASAccelerometer").startAccelerometer(e[0]).then(e=>{console.debug("[AdvancedAPI] startAccelerometer success"),o.invoke(Result.success(e))},(e,t)=>{console.debug("[AdvancedAPI] startAccelerometer fail errMsg = %o, code = %d",e,t),o.invoke(Result.fail([e,t]))})}function stopAccelerometer(...e){console.debug("[AdvancedAPI] start stopAccelerometer");let o=e.pop();requireAPI("ASAccelerometer").stopAccelerometer().then(e=>{console.debug("[AdvancedAPI] startAccelerometer success"),o.invoke(Result.success(e))},(e,t)=>{console.debug("[AdvancedAPI] startAccelerometer fail"),o.invoke(Result.fail([e,t]))})}function onCompassChange(...e){console.debug("[AdvancedAPI] start onCompassChange"),e=e.pop(),requireAPI("ASCompass").onCompassChange(e).then(e=>{console.debug("[AdvancedAPI] onCompassChange success")},(e,t)=>{console.debug("[AdvancedAPI] onCompassChange fail errMsg = %o, code = %d",e,t)})}function offCompassChange(...e){console.debug("[AdvancedAPI] start offCompassChange"),e=e.pop(),requireAPI("ASCompass").offCompassChange(e).then(e=>{console.debug("[AdvancedAPI] offCompassChange success")},(e,t)=>{console.debug("[AdvancedAPI] offCompassChange fail errMsg = %o, code = %d",e,t)})}function startCompass(...e){console.debug("[AdvancedAPI] start startCompass");let o=e.pop();requireAPI("ASCompass").startCompass().then(e=>{console.debug("[AdvancedAPI] startCompass success"),o.invoke(Result.success(e))},(e,t)=>{console.debug("[AdvancedAPI] startCompass fail"),o.invoke(Result.fail([e,t]))})}function stopCompass(...e){console.debug("[AdvancedAPI] start stopCompass");let o=e.pop();requireAPI("ASCompass").stopCompass().then(e=>{console.debug("[AdvancedAPI] stopCompass success"),o.invoke(Result.success(e))},(e,t)=>{console.debug("[AdvancedAPI] stopCompass fail"),o.invoke(Result.fail([e,t]))})}function onGyroscopeChange(...e){console.debug("[AdvancedAPI] start onGyroscopeChange"),e=e.pop(),requireAPI("ASGyroscope").onGyroscopeChange(e).then(e=>{console.debug("[AdvancedAPI] onGyroscopeChange success")},(e,t)=>{console.debug("[AdvancedAPI] onGyroscopeChange fail errMsg = %o, code = %d",e,t)})}function startGyroscope(...e){console.debug("[AdvancedAPI] start startCompass");let o=e.pop();requireAPI("ASGyroscope").startGyroscope(e[0]).then(e=>{console.debug("[AdvancedAPI] startCompass success"),o.invoke(Result.success(e))},(e,t)=>{console.debug("[AdvancedAPI] startCompass fail errMsg = %o, code = %d",e,t),o.invoke(Result.fail([e,t]))})}function stopGyroscope(...e){console.debug("[AdvancedAPI] start stopGyroscope");let o=e.pop();requireAPI("ASGyroscope").stopGyroscope().then(e=>{console.debug("[AdvancedAPI] stopGyroscope success"),o.invoke(Result.success(e))},(e,t)=>{console.debug("[AdvancedAPI] stopGyroscope fail errMsg = %o, code = %d",e,t),o.invoke(Result.fail([e,t]))})}function addPhoneContact(...e){let t=e.pop();e=e.pop()||{},requireAPI("ASContact").addPhoneContact(e).then(e=>{t.invoke(Result.success(e))},e=>{t.invoke(Result.fail(e))})}function vibrate(...e){let t=e.pop();requireAPI("ASVibrator").vibrate().then(e=>{t.invoke(Result.success(e))},e=>{t.invoke(Result.fail(e))})}function vibrateLong(...e){let t=e.pop();requireAPI("ASVibrator").vibrateLong().then(e=>{t.invoke(Result.success(e))},e=>{t.invoke(Result.fail(e))})}function vibrateShort(...e){let t=e.pop();requireAPI("ASVibrator").vibrateShort().then(e=>{t.invoke(Result.success(e))},e=>{t.invoke(Result.fail(e))})}function onUserCaptureScreen(...e){e=e.pop(),requireAPI("ASCapture").onUserCaptureScreen(e)}function offUserCaptureScreen(...e){e=e.pop(),requireAPI("ASCapture").offUserCaptureScreen(e)}function hideKeyboard(...e){let t=requireAPI("ASKeyboard"),o=e.pop();t.hideKeyboard().then(()=>{console.debug("[AdvancedAPI] hideKeyboard success"),o.invoke(Result.success())},(e,t)=>{console.debug("[AdvancedAPI] hideKeyboard fail, code: %d, error: %s",t,e),o.invoke(Result.fail())})}function onKeyboardHeightChange(...e){e=e.pop(),requireAPI("ASKeyboard").onKeyboardHeightChange(e)}function offKeyboardHeightChange(...e){e=e.pop(),requireAPI("ASKeyboard").offKeyboardHeightChange(e)}function login(...e){let t=e.pop();var e=e.pop(),o=requireAPI("ASAccount");console.debug("[AdvancedAPI] ASAccount login"),o.login(e).then(e=>{t.invoke(Result.success(e))},e=>{t.invoke(Result.fail(e))})}function getUserInfo(...e){let t=e.pop();var e=e.pop(),o=requireAPI("ASAccount");console.debug("[AdvancedAPI] ASAccount getUserInfo"),o.getUserInfo(e).then(e=>{t.invoke(Result.success(e))},e=>{t.invoke(Result.fail(e))})}function chooseImage(...e){console.debug("[AdvancedAPI] start chooseImage");let t=e.pop();var o=requireAPI("ASImage"),e=e[0];o.chooseImage(e).then(e=>{t.invoke(Result.success(e))},e=>{t.invoke(Result.fail(e))})}function getImageInfo(...e){console.debug("[AdvancedAPI] start getImageInfo");let t=e.pop();var o=requireAPI("ASImage"),e=e[0];o.getImageInfo(e).then(e=>{t.invoke(Result.success(e))},e=>{t.invoke(Result.fail(e))})}function saveImageToPhotosAlbum(...e){console.debug("[AdvancedAPI] start saveImageToPhotosAlbum");let t=e.pop();var o=requireAPI("ASImage"),e=e[0];o.saveImageToPhotosAlbum(e).then(e=>{t.invoke(Result.success(e))},e=>{t.invoke(Result.fail(e))})}function compressImage(...e){console.debug("[AdvancedAPI] start compressImage");let t=e.pop();var o=requireAPI("ASImage"),e=e[0];o.compressImage(e).then(e=>{t.invoke(Result.success(e))},e=>{t.invoke(Result.fail(e))})}function setScreenBrightness(...e){let t=e.pop();e=e.pop(),requireAPI("ASBrightness").setScreenBrightness(e).then(e=>{t.invoke(Result.success(e))},e=>{t.invoke(Result.fail(e))})}function getScreenBrightness(...e){let t=e.pop();requireAPI("ASBrightness").getScreenBrightness().then(e=>{console.info("[AdvancedAPI] getScreenBrightness raw = "+e[0].value),e=e[0].value/255,console.info("[AdvancedAPI] getScreenBrightness = "+e),t.invoke(Result.success({value:e}))},e=>{t.invoke(Result.fail(e))})}function setKeepScreenOn(...e){let t=e.pop();e=e.pop(),requireAPI("ASBrightness").asSetKeepScreenOn(e).then(()=>{t.invoke(Result.success())},()=>{t.invoke(Result.fail())})}function saveFile(...e){let t=e.pop();e=e.pop()||{},requireAPI("ASFile").saveFile(e).then(e=>{t.invoke(Result.success(e))}).catch(e=>{t.invoke(Result.fail(e))})}function getSavedFileList(...e){let t=e.pop();requireAPI("ASFile").getSavedFileList().then(e=>{t.invoke(Result.success(e))}).catch(e=>{t.invoke(Result.fail(e))})}function getSavedFileInfo(...e){let t=e.pop();e=e.pop()||{},requireAPI("ASFile").getSavedFileInfo(e).then(e=>{t.invoke(Result.success(e))}).catch(e=>{t.invoke(Result.fail(e))})}function removeSavedFile(...e){let t=e.pop();e=e.pop()||{},requireAPI("ASFile").removeSavedFile(e).then(e=>{t.invoke(Result.success(e))}).catch(e=>{t.invoke(Result.fail(e))})}function getFileInfo(...e){let t=e.pop();e=e.pop()||{},requireAPI("ASFile").getFileInfo(e).then(e=>{t.invoke(Result.success(e))}).catch(e=>{t.invoke(Result.fail(e))})}function openDocument(...e){let t=e.pop();e=e.pop()||{},requireAPI("ASFile").openDocument(e).then(e=>{t.invoke(Result.success(e))}).catch(e=>{t.invoke(Result.fail(e))})}function getFileSystemManager(){return requireAPI("ASFile").getFileSystemManager()}function createInnerAudioContext(){return console.debug("[AdvancedAPI] start createInnerAudioContext"),requireAPI("ASAudio").createInnerAudioContext()}function saveVideoToPhotosAlbum(...e){console.debug("[AdvancedAPI] start saveVideoToPhotosAlbum");let t=e.pop();var o=requireAPI("ASVideo"),e=e[0];o.saveVideoToPhotosAlbum(e).then(e=>{t.invoke(Result.success(e))},e=>{t.invoke(Result.fail(e))})}function getVideoInfo(...e){console.debug("[AdvancedAPI] start getVideoInfo");let t=e.pop();var o=requireAPI("ASVideo"),e=e[0];o.getVideoInfo(e).then(e=>{t.invoke(Result.success(e))},e=>{t.invoke(Result.fail(e))})}function scanCode(...e){console.debug("[AdvancedAPI] start scanCode");let t=e.pop();e=e[0],requireAPI("ASScan").scanCode(e).then(e=>{t.invoke(Result.success(e))},e=>{t.invoke(Result.fail(e))})}let asInterfaceList={getSystemInfoSync:{method:getSystemInfoSync,needPromise:!1,needCallback:!1},getDeviceInfo:{method:getDeviceInfo,needPromise:!1},getWindowInfo:{method:getWindowInfo,needPromise:!1},getAppBaseInfo:{method:getAppBaseInfo,needPromise:!1},getAppAuthorizeSetting:{method:getAppAuthorizeSetting,needPromise:!1},getSystemSetting:{method:getSystemSetting,needPromise:!1},openAppAuthorizeSetting:{method:openAppAuthorizeSetting},getLocation:{method:getLocation},onLocationChange:{method:onLocationChange},offLocationChange:{method:offLocationChange,needPromise:!1},startLocationUpdate:{method:startLocationUpdate},startLocationUpdateBackground:{method:startLocationUpdateBackground},stopLocationUpdate:{method:stopLocationUpdate},onLocationChangeError:{method:onLocationChangeError},offLocationChangeError:{method:offLocationChangeError},makePhoneCall:{method:makePhoneCall},request:{method:request},uploadFile:{method:uploadFile},downloadFile:{method:downloadFile},navigateTo:{method:navigateTo},redirectTo:{method:redirectTo},navigateBack:{method:navigateBack},openBluetoothAdapter:{method:openBluetoothAdapter},startBluetoothDevicesDiscovery:{method:startBluetoothDevicesDiscovery},onBluetoothDeviceFound:{method:onBluetoothDeviceFound,needPromise:!1,needCallback:!1},offBluetoothDeviceFound:{method:offBluetoothDeviceFound,needPromise:!1,needCallback:!1},stopBluetoothDevicesDiscovery:{method:stopBluetoothDevicesDiscovery},onBluetoothAdapterStateChange:{method:onBluetoothAdapterStateChange,needPromise:!1,needCallback:!1},offBluetoothAdapterStateChange:{method:offBluetoothAdapterStateChange,needPromise:!1,needCallback:!1},getConnectedBluetoothDevices:{method:getConnectedBluetoothDevices},getBluetoothAdapterState:{method:getBluetoothAdapterState},closeBluetoothAdapter:{method:closeBluetoothAdapter},getBluetoothDevices:{method:getBluetoothDevices},setBLEMTU:{method:setBLEMTU},writeBLECharacteristicValue:{method:writeBLECharacteristicValue},readBLECharacteristicValue:{method:readBLECharacteristicValue},onBLEConnectionStateChange:{method:onBLEConnectionStateChange,needPromise:!1,needCallback:!1},offBLEConnectionStateChange:{method:offBLEConnectionStateChange,needPromise:!1,needCallback:!1},onBLECharacteristicValueChange:{method:onBLECharacteristicValueChange,needPromise:!1,needCallback:!1},offBLECharacteristicValueChange:{method:offBLECharacteristicValueChange,needPromise:!1,needCallback:!1},notifyBLECharacteristicValueChange:{method:notifyBLECharacteristicValueChange},getBLEDeviceServices:{method:getBLEDeviceServices},getBLEDeviceRSSI:{method:getBLEDeviceRSSI},getBLEDeviceCharacteristics:{method:getBLEDeviceCharacteristics},createBLEConnection:{method:createBLEConnection},closeBLEConnection:{method:closeBLEConnection},onAccelerometerChange:{method:onAccelerometerChange,needPromise:!1,needCallback:!1},offAccelerometerChange:{method:offAccelerometerChange,needPromise:!1,needCallback:!1},startAccelerometer:{method:startAccelerometer},stopAccelerometer:{method:stopAccelerometer},onCompassChange:{method:onCompassChange,needPromise:!1,needCallback:!1},offCompassChange:{method:offCompassChange,needPromise:!1,needCallback:!1},startCompass:{method:startCompass},stopCompass:{method:stopCompass},onGyroscopeChange:{method:onGyroscopeChange,needPromise:!1,needCallback:!1},startGyroscope:{method:startGyroscope},stopGyroscope:{method:stopGyroscope},startWifi:{method:startWifi},stopWifi:{method:stopWifi},getConnectedWifi:{method:getConnectedWifi},getWifiList:{method:getWifiList},onGetWifiList:{method:onGetWifiList,needPromise:!1,needCallback:!1},offGetWifiList:{method:offGetWifiList,needPromise:!1,needCallback:!1},connectWifi:{method:connectWifi},onWifiConnected:{method:onWifiConnected,needPromise:!1,needCallback:!1},offWifiConnected:{method:offWifiConnected,needPromise:!1,needCallback:!1},onWifiConnectedWithPartialInfo:{method:onWifiConnectedWithPartialInfo,needPromise:!1,needCallback:!1},offWifiConnectedWithPartialInfo:{method:offWifiConnectedWithPartialInfo,needPromise:!1,needCallback:!1},startSoterAuthentication:{method:startSoterAuthentication},checkIsSupportSoterAuthentication:{method:checkIsSupportSoterAuthentication},checkIsSoterEnrolledInDevice:{method:checkIsSoterEnrolledInDevice},addPhoneContact:{method:addPhoneContact},vibrate:{method:vibrate},vibrateLong:{method:vibrateLong},vibrateShort:{method:vibrateShort},onUserCaptureScreen:{method:onUserCaptureScreen,needPromise:!1,needCallback:!1},offUserCaptureScreen:{method:offUserCaptureScreen,needPromise:!1,needCallback:!1},hideKeyboard:{method:hideKeyboard},onKeyboardHeightChange:{method:onKeyboardHeightChange,needPromise:!1,needCallback:!1},offKeyboardHeightChange:{method:offKeyboardHeightChange,needPromise:!1,needCallback:!1},login:{method:login},getUserInfo:{method:getUserInfo},chooseImage:{method:chooseImage},getImageInfo:{method:getImageInfo},saveImageToPhotosAlbum:{method:saveImageToPhotosAlbum},compressImage:{method:compressImage},setScreenBrightness:{method:setScreenBrightness},getScreenBrightness:{method:getScreenBrightness},setKeepScreenOn:{method:setKeepScreenOn},saveFile:{method:saveFile},getSavedFileList:{method:getSavedFileList},getSavedFileInfo:{method:getSavedFileInfo},removeSavedFile:{method:removeSavedFile},getFileInfo:{method:getFileInfo},openDocument:{method:openDocument},getFileSystemManager:{method:getFileSystemManager,needPromise:!1,needCallback:!1},createInnerAudioContext:{method:createInnerAudioContext,needPromise:!1,needCallback:!1},saveVideoToPhotosAlbum:{method:saveVideoToPhotosAlbum},getVideoInfo:{method:getVideoInfo},scanCode:{method:scanCode}};function invokeModule(e,...t){console.debug("[AdvancedAPI] invokeModule moduleName = %s",e);var o=t.pop();if("number"==typeof o){let e=jsCallbackMap.get(o);e||(e=new JSCallback({id:o}),jsCallbackMap.set(o,e)),t.push(e)}else t.push(o);return o=asInterfaceList[e],triggerInterceptInvoke(e,t),triggerInterceptReturnValue(e,o=o.method.apply(null,t)),o}function triggerInterceptInvoke(e,t){var o=requireAPI("ASInterceptor");!1!==asInterfaceList[e].needCallback&&((t=[...t]).pop(),o.invoke(e,t))}function triggerInterceptReturnValue(e,t){requireAPI("ASInterceptor").returnValue(e,t)}function createAs(){let e={};return Object.keys(asInterfaceList).forEach(o=>{Object.defineProperty(e,o,{get:()=>(...e)=>{e=(t=interceptCallback(e,o,asInterfaceList[o].needPromise,asInterfaceList[o].needCallback)).args||[];var t=t.promise,e=invokeModule(o,...e);return t?t.promise:e}})}),e}let as=createAs(),AdvancedApi={init:function(e,t){var o;globalThis.as&&globalThis.requireAPI||(console.debug("[AdvancedAPI] init"),globalThis.as=as,globalThis.requireAPI=requireAPI$1,globalThis.isStageModel=!0,globalThis.abilityContext=e,media.createAVRecorder().then(e=>{globalThis.commonAvRecorder=e}),o=bundleManager.BundleFlag.GET_BUNDLE_INFO_WITH_SIGNATURE_INFO|bundleManager.BundleFlag.GET_BUNDLE_INFO_WITH_APPLICATION,globalThis.bundleInfoForSelf=bundleManager.getBundleInfoForSelfSync(o),globalThis.lastWindow=t,initContextOnStageModel(e))}};export default AdvancedApi;export{as,createAs}; diff --git a/ohos/AdvancedAPI_OHOS/project/advancedApiHsp/advanced_api_hsp/src/main/module.json5 b/ohos/AdvancedAPI_OHOS/project/advancedApiHsp/advanced_api_hsp/src/main/module.json5 new file mode 100644 index 0000000000..c2a8a16589 --- /dev/null +++ b/ohos/AdvancedAPI_OHOS/project/advancedApiHsp/advanced_api_hsp/src/main/module.json5 @@ -0,0 +1,14 @@ +{ + "module": { + "name": "advanced_api_hsp", + "type": "shared", + "description": "$string:shared_desc", + "deviceTypes": [ + "phone", + "tablet", + "2in1" + ], + "deliveryWithInstall": true, + "pages": "$profile:main_pages" + } +} \ No newline at end of file diff --git a/ohos/AdvancedAPI_OHOS/project/advancedApiHsp/advanced_api_hsp/src/main/resources/base/element/string.json b/ohos/AdvancedAPI_OHOS/project/advancedApiHsp/advanced_api_hsp/src/main/resources/base/element/string.json new file mode 100644 index 0000000000..98e1d8a84b --- /dev/null +++ b/ohos/AdvancedAPI_OHOS/project/advancedApiHsp/advanced_api_hsp/src/main/resources/base/element/string.json @@ -0,0 +1,8 @@ +{ + "string": [ + { + "name": "shared_desc", + "value": "description" + } + ] +} \ No newline at end of file diff --git a/ohos/AdvancedAPI_OHOS/project/advancedApiHsp/advanced_api_hsp/src/main/resources/base/profile/main_pages.json b/ohos/AdvancedAPI_OHOS/project/advancedApiHsp/advanced_api_hsp/src/main/resources/base/profile/main_pages.json new file mode 100644 index 0000000000..1898d94f58 --- /dev/null +++ b/ohos/AdvancedAPI_OHOS/project/advancedApiHsp/advanced_api_hsp/src/main/resources/base/profile/main_pages.json @@ -0,0 +1,5 @@ +{ + "src": [ + "pages/Index" + ] +} diff --git a/ohos/AdvancedAPI_OHOS/project/advancedApiHsp/advanced_api_hsp/src/ohosTest/ets/test/Ability.test.ets b/ohos/AdvancedAPI_OHOS/project/advancedApiHsp/advanced_api_hsp/src/ohosTest/ets/test/Ability.test.ets new file mode 100644 index 0000000000..85c78f6757 --- /dev/null +++ b/ohos/AdvancedAPI_OHOS/project/advancedApiHsp/advanced_api_hsp/src/ohosTest/ets/test/Ability.test.ets @@ -0,0 +1,35 @@ +import { hilog } from '@kit.PerformanceAnalysisKit'; +import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium'; + +export default function abilityTest() { + describe('ActsAbilityTest', () => { + // Defines a test suite. Two parameters are supported: test suite name and test suite function. + beforeAll(() => { + // Presets an action, which is performed only once before all test cases of the test suite start. + // This API supports only one parameter: preset action function. + }) + beforeEach(() => { + // Presets an action, which is performed before each unit test case starts. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: preset action function. + }) + afterEach(() => { + // Presets a clear action, which is performed after each unit test case ends. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: clear action function. + }) + afterAll(() => { + // Presets a clear action, which is performed after all test cases of the test suite end. + // This API supports only one parameter: clear action function. + }) + it('assertContain', 0, () => { + // Defines a test case. This API supports three parameters: test case name, filter parameter, and test case function. + hilog.info(0x0000, 'testTag', '%{public}s', 'it begin'); + let a = 'abc'; + let b = 'b'; + // Defines a variety of assertion methods, which are used to declare expected boolean conditions. + expect(a).assertContain(b); + expect(a).assertEqual(a); + }) + }) +} \ No newline at end of file diff --git a/ohos/AdvancedAPI_OHOS/project/advancedApiHsp/advanced_api_hsp/src/ohosTest/ets/test/List.test.ets b/ohos/AdvancedAPI_OHOS/project/advancedApiHsp/advanced_api_hsp/src/ohosTest/ets/test/List.test.ets new file mode 100644 index 0000000000..794c7dc4ed --- /dev/null +++ b/ohos/AdvancedAPI_OHOS/project/advancedApiHsp/advanced_api_hsp/src/ohosTest/ets/test/List.test.ets @@ -0,0 +1,5 @@ +import abilityTest from './Ability.test'; + +export default function testsuite() { + abilityTest(); +} \ No newline at end of file diff --git a/ohos/AdvancedAPI_OHOS/project/advancedApiHsp/advanced_api_hsp/src/ohosTest/module.json5 b/ohos/AdvancedAPI_OHOS/project/advancedApiHsp/advanced_api_hsp/src/ohosTest/module.json5 new file mode 100644 index 0000000000..cf29dc042c --- /dev/null +++ b/ohos/AdvancedAPI_OHOS/project/advancedApiHsp/advanced_api_hsp/src/ohosTest/module.json5 @@ -0,0 +1,13 @@ +{ + "module": { + "name": "advanced_api_hsp_test", + "type": "feature", + "deviceTypes": [ + "phone", + "tablet", + "2in1" + ], + "deliveryWithInstall": true, + "installationFree": false + } +} \ No newline at end of file diff --git a/ohos/AdvancedAPI_OHOS/project/advancedApiHsp/advanced_api_hsp/src/test/List.test.ets b/ohos/AdvancedAPI_OHOS/project/advancedApiHsp/advanced_api_hsp/src/test/List.test.ets new file mode 100644 index 0000000000..bb5b5c3731 --- /dev/null +++ b/ohos/AdvancedAPI_OHOS/project/advancedApiHsp/advanced_api_hsp/src/test/List.test.ets @@ -0,0 +1,5 @@ +import localUnitTest from './LocalUnit.test'; + +export default function testsuite() { + localUnitTest(); +} \ No newline at end of file diff --git a/ohos/AdvancedAPI_OHOS/project/advancedApiHsp/advanced_api_hsp/src/test/LocalUnit.test.ets b/ohos/AdvancedAPI_OHOS/project/advancedApiHsp/advanced_api_hsp/src/test/LocalUnit.test.ets new file mode 100644 index 0000000000..165fc1615e --- /dev/null +++ b/ohos/AdvancedAPI_OHOS/project/advancedApiHsp/advanced_api_hsp/src/test/LocalUnit.test.ets @@ -0,0 +1,33 @@ +import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium'; + +export default function localUnitTest() { + describe('localUnitTest', () => { + // Defines a test suite. Two parameters are supported: test suite name and test suite function. + beforeAll(() => { + // Presets an action, which is performed only once before all test cases of the test suite start. + // This API supports only one parameter: preset action function. + }); + beforeEach(() => { + // Presets an action, which is performed before each unit test case starts. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: preset action function. + }); + afterEach(() => { + // Presets a clear action, which is performed after each unit test case ends. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: clear action function. + }); + afterAll(() => { + // Presets a clear action, which is performed after all test cases of the test suite end. + // This API supports only one parameter: clear action function. + }); + it('assertContain', 0, () => { + // Defines a test case. This API supports three parameters: test case name, filter parameter, and test case function. + let a = 'abc'; + let b = 'b'; + // Defines a variety of assertion methods, which are used to declare expected boolean conditions. + expect(a).assertContain(b); + expect(a).assertEqual(a); + }); + }); +} \ No newline at end of file diff --git a/ohos/AdvancedAPI_OHOS/project/advancedApiHsp/build-profile.json5 b/ohos/AdvancedAPI_OHOS/project/advancedApiHsp/build-profile.json5 new file mode 100644 index 0000000000..2683fb87c1 --- /dev/null +++ b/ohos/AdvancedAPI_OHOS/project/advancedApiHsp/build-profile.json5 @@ -0,0 +1,44 @@ +{ + "app": { + "signingConfigs": [], + "products": [ + { + "name": "default", + "signingConfig": "default", + "compatibleSdkVersion": "5.0.0(12)", + "runtimeOS": "HarmonyOS", + "buildOption": { + "strictMode": { + "caseSensitiveCheck": true + } + } + } + ], + "buildModeSet": [ + { + "name": "debug", + }, + { + "name": "release" + } + ] + }, + "modules": [ + { + "name": "advanced_api_har", + "srcPath": "./advanced_api_har", + }, + { + "name": "advanced_api_hsp", + "srcPath": "./advanced_api_hsp", + "targets": [ + { + "name": "default", + "applyToProducts": [ + "default" + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/ohos/AdvancedAPI_OHOS/project/advancedApiHsp/code-linter.json5 b/ohos/AdvancedAPI_OHOS/project/advancedApiHsp/code-linter.json5 new file mode 100644 index 0000000000..77b31b517a --- /dev/null +++ b/ohos/AdvancedAPI_OHOS/project/advancedApiHsp/code-linter.json5 @@ -0,0 +1,20 @@ +{ + "files": [ + "**/*.ets" + ], + "ignore": [ + "**/src/ohosTest/**/*", + "**/src/test/**/*", + "**/src/mock/**/*", + "**/node_modules/**/*", + "**/oh_modules/**/*", + "**/build/**/*", + "**/.preview/**/*" + ], + "ruleSet": [ + "plugin:@performance/recommended", + "plugin:@typescript-eslint/recommended" + ], + "rules": { + } +} \ No newline at end of file diff --git a/ohos/AdvancedAPI_OHOS/project/advancedApiHsp/hvigorfile.ts b/ohos/AdvancedAPI_OHOS/project/advancedApiHsp/hvigorfile.ts new file mode 100644 index 0000000000..f3cb9f1a87 --- /dev/null +++ b/ohos/AdvancedAPI_OHOS/project/advancedApiHsp/hvigorfile.ts @@ -0,0 +1,6 @@ +import { appTasks } from '@ohos/hvigor-ohos-plugin'; + +export default { + system: appTasks, /* Built-in plugin of Hvigor. It cannot be modified. */ + plugins:[] /* Custom plugin to extend the functionality of Hvigor. */ +} diff --git a/ohos/AdvancedAPI_OHOS/project/advancedApiHsp/oh-package.json5 b/ohos/AdvancedAPI_OHOS/project/advancedApiHsp/oh-package.json5 new file mode 100644 index 0000000000..bb12751b97 --- /dev/null +++ b/ohos/AdvancedAPI_OHOS/project/advancedApiHsp/oh-package.json5 @@ -0,0 +1,10 @@ +{ + "modelVersion": "5.0.0", + "description": "Please describe the basic information.", + "dependencies": { + }, + "devDependencies": { + "@ohos/hypium": "1.0.19", + "@ohos/hamock": "1.0.0" + } +} diff --git a/ohos/AdvancedAPI_OHOS/scripts/build_advancedapi.sh b/ohos/AdvancedAPI_OHOS/scripts/build_advancedapi.sh new file mode 100644 index 0000000000..a70b91a568 --- /dev/null +++ b/ohos/AdvancedAPI_OHOS/scripts/build_advancedapi.sh @@ -0,0 +1,103 @@ +#!/bin/bash +# *********************************************************************** +# Copyright: (c) Huawei Technologies Co., Ltd. 2019. All rights reserved. +# script for build +# version: 1.0.0 +# change log: +# *********************************************************************** +set -ex +set -o pipefail + +#先cd到脚本所在路径,再实现其他处理逻辑,否则该脚本执行会依赖脚本执行的路径 +basepath=$(cd `dirname $0`; pwd) +cd $basepath + +cd .. + +if [[ ${JDK_PATH} != "" ]]; then + export JAVA_HOME=${JDK_PATH} + export PATH=${JDK_PATH}/bin:$PATH +fi + +#代码根路径 全局参数 codepath +codepath=${WORKSPACE}"/FastAPPCenter" + + +#----安装打包需要的依赖 +cd $codepath +npm install + +# 设置编译环境 +npm run build:advanced + +zip_file=${pkg_name} + +cd $codepath/project/advancedApiHsp/advanced_api_hsp/src/main/ets/ +mkdir utils + +cd $codepath/project/advancedApiHsp/advanced_api_har/src/main/ +mkdir ets +cd ets +mkdir utils +cd .. +mkdir resources + +cp $codepath/dist/advancedapi.min.js $codepath/project/advancedApiHsp/advanced_api_hsp/src/main/ets/utils/ + +cp $codepath/dist/advancedapi.min.js $codepath/project/advancedApiHsp/advanced_api_har/src/main/ets/utils/ + +cd $codepath + +mkdir hwsdk + +cp -R ${hwsdk}/hmscore ./hwsdk/ +cp -R ${hwsdk}/licenses ./hwsdk/ +cp -R ${hwsdk}/openharmony ./hwsdk/ + +cd ./hwsdk/hmscore/4.0.0/toolchains/modulecheck + +sed -i 's/atomicService/shared/g' app.json + +cd $codepath/project/advancedApiHsp + +ohpm install + +echo -e "{\r\n \"dependencies\":{\r\n \"@ohos/hvigor\":\"2.3.0-s\",\r\n \"@ohos/hvigor-ohos-plugin\":\"2.3.0-s\"\r\n}\r\n}" > package.json + +npm install + +echo "hwsdk.dir="$codepath/hwsdk > local.properties + +node ./node_modules/@ohos/hvigor/bin/hvigor.js --mode project -p product=default assembleApp --parallel --incremental --daemon + +node ./node_modules/@ohos/hvigor/bin/hvigor.js --mode module -p product=default assembleHar --parallel --incremental --daemon + +cd $codepath +mkdir zipPath +cd zipPath +mkdir hsp +mkdir har +cp $codepath/project/advancedApiHsp/advanced_api_har/build/default/outputs/default/advanced_api_har.har $codepath/zipPath/har/ +cp $codepath/project/advancedApiHsp/advanced_api_hsp/build/default/outputs/default/advanced_api_hsp.har $codepath/zipPath/hsp/ +cp $codepath/project/advancedApiHsp/advanced_api_hsp/build/default/outputs/default/advanced_api_hsp-default-signed.hsp $codepath/zipPath/hsp/ + +# 插件工程打包 +rm $codepath/project/AdvancedTemplete/entry/src/main/ets/har/advanced_api_har.har +cp $codepath/project/advancedApiHsp/advanced_api_har/build/default/outputs/default/advanced_api_har.har $codepath/project/AdvancedTemplete/entry/src/main/ets/har +mkdir $codepath/project/UniappToAtomicService/project +cp -r $codepath/project/AdvancedTemplete $codepath/project/UniappToAtomicService/project +cd $codepath/project/UniappToAtomicService +zip -r $codepath/zipPath/UniappToAtomicService ./ + +cd $codepath/zipPath +zip -r ${zip_file} ./ + +bash ${WORKSPACE}/Script/clouddragon/build2.0/service/getPackageInfo.sh "FastAPPCenter/zipPath" "${zip_file}" + +if [[ $releaseVersion == "" ]];then + echo "This build is snapshot" + echo buildVersion="snapshot_${ENV_PIPELINE_STARTTIME}" >> ${WORKSPACE}/buildInfo.properties +else + echo "This build is release" + echo buildVersion="release_${ENV_PIPELINE_STARTTIME}" >> ${WORKSPACE}/buildInfo.properties +fi \ No newline at end of file diff --git a/ohos/AdvancedAPI_OHOS/scripts/build_assemble.sh b/ohos/AdvancedAPI_OHOS/scripts/build_assemble.sh new file mode 100644 index 0000000000..3898edf0f6 --- /dev/null +++ b/ohos/AdvancedAPI_OHOS/scripts/build_assemble.sh @@ -0,0 +1,55 @@ +#!/bin/bash +# *********************************************************************** +# Copyright: (c) Huawei Technologies Co., Ltd. 2019. All rights reserved. +# script for build +# version: 1.0.0 +# change log: +# *********************************************************************** +set -ex +set -o pipefail + +# ============================================================================= +#进入脚本路径 +basepath=$(cd `dirname $0`; pwd) +cd ${basepath} +echo ${basepath} + +# ============================================================================= +# "执行qafapi.js编译脚本" +bash build_qafapi.sh + +# ============================================================================= +# "执行libNative.so编译脚本" +bash build_cpp.sh + +# ============================================================================= +# 流水线build2.0编译后打包 + +cd ${basepath} + +# 新建打包目录 +rm -rf ${WORKSPACE}/package_assemble +mkdir -p ${WORKSPACE}/package_assemble +pkg_path=${WORKSPACE}/package_assemble + +# 获取qafapi.min.js放到新建打包目录 +cp ${WORKSPACE}/${codeRootDir}/dist/qafapi.min.js ${pkg_path} +cp -r ${WORKSPACE}/${codeRootDir}/dist/bridge ${pkg_path} + +# 获取libNativeAPI.so放到新建打包目录 +cp ${WORKSPACE}/${codeRootDir}/thirdparty/libs/ohos/${OHOS_ARCH}/libNativeAPI.so ${pkg_path} + +# 压缩在根目录创建的输出包文件夹并放置在当前脚本目录以qafapi.zip命名 +zip -r ${basepath}/qafapi.zip ${pkg_path} + +echo "查看待打包目录" +cd ${pkg_path} +ls + +echo "查看已经打包目录" +cd ${basepath} +ls + +# ============================================================================= +# 发布包 +bash ${WORKSPACE}/Script/clouddragon/build2.0/service/getPackageInfo.sh "${codeRootDir}" "qafapi.zip" \ No newline at end of file diff --git a/ohos/AdvancedAPI_OHOS/scripts/build_codecheck.sh b/ohos/AdvancedAPI_OHOS/scripts/build_codecheck.sh new file mode 100644 index 0000000000..c8cbb6c704 --- /dev/null +++ b/ohos/AdvancedAPI_OHOS/scripts/build_codecheck.sh @@ -0,0 +1,7 @@ +#!/bin/sh + +#进入到业务编译脚本的执行路径下 +cd ../../../scripts +chmod +x *.sh +#方式1:执行业务编译脚本(该脚本只执行C/++的编译操作,不进行打包处理包等业务逻辑) +sh build_cpp.sh diff --git a/ohos/AdvancedAPI_OHOS/src/advancedApi/as/account/account.js b/ohos/AdvancedAPI_OHOS/src/advancedApi/as/account/account.js new file mode 100644 index 0000000000..4584ce59e1 --- /dev/null +++ b/ohos/AdvancedAPI_OHOS/src/advancedApi/as/account/account.js @@ -0,0 +1,33 @@ +/** + * Copyright (c) Huawei Technologies Co., Ltd. 2023-2023. All rights reserved. + * Description: advanced as account api + * Create: 04/13/2023 + * Notes: N/A + */ +import Result from '../../../base/util/Result' + +export function login(...args) { + const callback = args.pop() + const obj = args.pop() + const account = requireAPI('ASAccount') + console.debug('[AdvancedAPI] ASAccount login') + + account.login(obj).then(data => { + callback.invoke(Result.success(data)) + }, (err) => { + callback.invoke(Result.fail(err)) + }) +} + +export function getUserInfo(...args) { + const callback = args.pop() + const obj = args.pop() + const account = requireAPI('ASAccount') + console.debug('[AdvancedAPI] ASAccount getUserInfo') + + account.getUserInfo(obj).then(data => { + callback.invoke(Result.success(data)) + }, (err) => { + callback.invoke(Result.fail(err)) + }) +} diff --git a/ohos/AdvancedAPI_OHOS/src/advancedApi/as/base/arrayBuffer2Base64.js b/ohos/AdvancedAPI_OHOS/src/advancedApi/as/base/arrayBuffer2Base64.js new file mode 100644 index 0000000000..bca12f01ab --- /dev/null +++ b/ohos/AdvancedAPI_OHOS/src/advancedApi/as/base/arrayBuffer2Base64.js @@ -0,0 +1,4 @@ +export function arrayBufferToBase64 (buf) { + const buffer = requireAPI('ASBuffer') + return buffer.arrayBufferToBase64(buf) +} diff --git a/ohos/AdvancedAPI_OHOS/src/advancedApi/as/bluetooth/bluetooth.js b/ohos/AdvancedAPI_OHOS/src/advancedApi/as/bluetooth/bluetooth.js new file mode 100644 index 0000000000..2ffe2fad83 --- /dev/null +++ b/ohos/AdvancedAPI_OHOS/src/advancedApi/as/bluetooth/bluetooth.js @@ -0,0 +1,227 @@ +import Result from '../../../base/util/Result' + +export function openBluetoothAdapter(...args) { + const callback = args.pop() + const bluetooth = requireAPI('ASBluetooth') + bluetooth.openBluetoothAdapter().then(data => { + callback.invoke(Result.success(data)) + }, (data) => { + callback.invoke(Result.fail(...data)) + }) +} + +export function closeBluetoothAdapter(...args) { + const callback = args.pop() + const bluetooth = requireAPI('ASBluetooth') + bluetooth.closeBluetoothAdapter().then(data => { + callback.invoke(Result.success(data)) + }, (data) => { + callback.invoke(Result.fail(...data)) + }) +} + +export function startBluetoothDevicesDiscovery(...args) { + const callback = args.pop() + const params = args.pop() + const bluetooth = requireAPI('ASBluetooth') + bluetooth.startBluetoothDevicesDiscovery(params).then(data => { + callback.invoke(Result.success(data)) + }, (data) => { + callback.invoke(Result.fail(...data)) + }) +} + +export function stopBluetoothDevicesDiscovery(...args) { + const callback = args.pop() + const bluetooth = requireAPI('ASBluetooth') + bluetooth.stopBluetoothDevicesDiscovery().then(data => { + callback.invoke(Result.success(data)) + }, (data) => { + callback.invoke(Result.fail(...data)) + }) +} + +export function onBluetoothDeviceFound(...args) { + const cb = args.pop() + const bluetooth = requireAPI('ASBluetooth') + bluetooth.onBluetoothDeviceFound(cb) +} + +export function offBluetoothDeviceFound(...args) { + const cb = args.pop() + const bluetooth = requireAPI('ASBluetooth') + bluetooth.offBluetoothDeviceFound(cb) +} + +export function onBluetoothAdapterStateChange(...args) { + const cb = args.pop() + const bluetooth = requireAPI('ASBluetooth') + bluetooth.onBluetoothAdapterStateChange(cb) +} + +export function offBluetoothAdapterStateChange(...args) { + const cb = args.pop() + const bluetooth = requireAPI('ASBluetooth') + bluetooth.offBluetoothAdapterStateChange(cb) +} + +export function getBluetoothDevices(...args) { + const callback = args.pop() + const bluetooth = requireAPI('ASBluetooth') + bluetooth.getBluetoothDevices().then(data => { + const devices = (data && data[0] && data[0][0]) || {} + callback.invoke(Result.success(devices)) + }, (data) => { + console.info('[AdvancedAPI] getBluetoothDevices fail' + JSON.stringify(data)) + callback.invoke(Result.fail(...data)) + }) +} + +export function getConnectedBluetoothDevices(...args) { + const callback = args.pop() + const params = args.pop() + const bluetooth = requireAPI('ASBluetooth') + bluetooth.getConnectedBluetoothDevices(params).then(data => { + console.info('[AdvancedAPI] getConnectedBluetoothDevices success' + JSON.stringify(data)) + callback.invoke(Result.success(data)) + }, (data) => { + console.info('[AdvancedAPI] getConnectedBluetoothDevices fail' + JSON.stringify(data)) + callback.invoke(Result.fail(...data)) + }) +} + +export function getBluetoothAdapterState(...args) { + const callback = args.pop() + const bluetooth = requireAPI('ASBluetooth') + bluetooth.getBluetoothAdapterState().then(data => { + callback.invoke(Result.success(data)) + }, (data) => { + callback.invoke(Result.fail(...data)) + }) +} + +export function setBLEMTU(...args) { + const callback = args.pop() + const params = args.pop() + const bluetooth = requireAPI('ASBluetooth') + bluetooth.asSetBLEMTU(params).then(data => { + callback.invoke(Result.success(data)) + }, (data) => { + callback.invoke(Result.fail(...data)) + }) +} + +export function writeBLECharacteristicValue(...args) { + const callback = args.pop() + const params = args.pop() + const bluetooth = requireAPI('ASBluetooth') + bluetooth.asWriteBLECharacteristicValue(params).then(data => { + callback.invoke(Result.success(data)) + }, (data) => { + callback.invoke(Result.fail(...data)) + }) +} + +export function readBLECharacteristicValue(...args) { + const callback = args.pop() + const params = args.pop() + const bluetooth = requireAPI('ASBluetooth') + bluetooth.asReadBLECharacteristicValue(params).then(data => { + callback.invoke(Result.success(data)) + }, (data) => { + callback.invoke(Result.fail(...data)) + }) +} + +export function onBLEConnectionStateChange(...args) { + const callback = args.pop() + const bluetooth = requireAPI('ASBluetooth') + bluetooth.asOnBLEConnectionStateChange(callback) +} + +export function offBLEConnectionStateChange(...args) { + const cb = args.pop() + const bluetooth = requireAPI('ASBluetooth') + bluetooth.asOffBLEConnectionStateChange(cb) +} + +export function onBLECharacteristicValueChange(...args) { + const callback = args.pop() + const bluetooth = requireAPI('ASBluetooth') + bluetooth.asOnBLECharacteristicValueChange(callback) +} + +export function offBLECharacteristicValueChange(...args) { + const cb = args.pop() + const bluetooth = requireAPI('ASBluetooth') + bluetooth.asOffBLECharacteristicValueChange(cb) +} + +export function notifyBLECharacteristicValueChange(...args) { + const callback = args.pop() + const params = args.pop() + const bluetooth = requireAPI('ASBluetooth') + bluetooth.asNotifyBLECharacteristicValueChange(params).then(data => { + callback.invoke(Result.success(data)) + }, (data) => { + callback.invoke(Result.fail(...data)) + }) +} + +export function getBLEDeviceServices(...args) { + const callback = args.pop() + const params = args.pop() + const bluetooth = requireAPI('ASBluetooth') + bluetooth.asGetBLEDeviceServices(params).then(data => { + callback.invoke(Result.success(data[0][0])) + }, (data) => { + callback.invoke(Result.fail(...data)) + }) +} + +// TODO:异常参数处理 +export function getBLEDeviceRSSI(...args) { + const callback = args.pop() + const params = args.pop() + const bluetooth = requireAPI('ASBluetooth') + bluetooth.asGetBLEDeviceRSSI(params).then((data) => { + callback.invoke(Result.success(data)) + }, (data) => { + callback.invoke(Result.fail(...data)) + }) +} + +export function getBLEDeviceCharacteristics(...args) { + console.debug('[AdvancedAPI] enter getBLEDeviceCharacteristics') + const callback = args.pop() + const params = args.pop() + const bluetooth = requireAPI('ASBluetooth') + bluetooth.asGetBLEDeviceCharacteristics(params).then(data => { + callback.invoke(Result.success(data[0])) + }, (data) => { + callback.invoke(Result.fail(...data)) + }) +} + +export function createBLEConnection(...args) { + const callback = args.pop() + const params = args.pop() + const bluetooth = requireAPI('ASBluetooth') + const { deviceId, timeout } = params || {} + bluetooth.asCreateBLEConnection({ deviceId, timeout }).then(data => { + callback.invoke(Result.success(data)) + }, (data) => { + callback.invoke(Result.fail(...data)) + }) +} + +export function closeBLEConnection(...args) { + const callback = args.pop() + const params = args.pop() + const bluetooth = requireAPI('ASBluetooth') + bluetooth.asCloseBLEConnection({ deviceId: params ? params.deviceId : undefined }).then(data => { + callback.invoke(Result.success(data)) + }, (data) => { + callback.invoke(Result.fail(...data)) + }) +} diff --git a/ohos/AdvancedAPI_OHOS/src/advancedApi/as/device/accelerometer.js b/ohos/AdvancedAPI_OHOS/src/advancedApi/as/device/accelerometer.js new file mode 100644 index 0000000000..da3aab38e3 --- /dev/null +++ b/ohos/AdvancedAPI_OHOS/src/advancedApi/as/device/accelerometer.js @@ -0,0 +1,62 @@ +/** + * Copyright (c) Huawei Technologies Co., Ltd. 2023-2023. All rights reserved. + * Description: Advanced API accelerometer + * Author: 00430169 + * Create: 23/3/2023 + * Notes: N/A + */ + +import Result from '../../../base/util/Result' + +export function onAccelerometerChange (...args) { + console.debug('[AdvancedAPI] start onAccelerometerChange') + const callback = args.pop() + const accelerometer = requireAPI('ASAccelerometer') + + accelerometer.onAccelerometerChange(callback).then(data => { + console.debug('[AdvancedAPI] onAccelerometerChange success') + }, (data, code) => { + console.debug('[AdvancedAPI] onAccelerometerChange fail errMsg = %o, code = %d', data, code) + }) +} + +export function offAccelerometerChange (...args) { + console.debug('[AdvancedAPI] start offAccelerometerChange') + const callback = args.pop() + const accelerometer = requireAPI('ASAccelerometer') + + accelerometer.offAccelerometerChange(callback).then(data => { + console.debug('[AdvancedAPI] offAccelerometerChange success') + }, (data, code) => { + console.debug('[AdvancedAPI] offAccelerometerChange fail errMsg = %o, code = %d', data, code) + }) +} + +export function startAccelerometer (...args) { + console.debug('[AdvancedAPI] start startAccelerometer') + const callback = args.pop() + const accelerometer = requireAPI('ASAccelerometer') + + accelerometer.startAccelerometer(args[0]).then(data => { + console.debug('[AdvancedAPI] startAccelerometer success') + callback.invoke(Result.success(data)) + }, (data, code) => { + console.debug('[AdvancedAPI] startAccelerometer fail errMsg = %o, code = %d', data, code) + callback.invoke(Result.fail([data, code])) + }) +} + +export function stopAccelerometer (...args) { + console.debug('[AdvancedAPI] start stopAccelerometer') + const callback = args.pop() + const accelerometer = requireAPI('ASAccelerometer') + + accelerometer.stopAccelerometer().then(data => { + console.debug('[AdvancedAPI] startAccelerometer success') + callback.invoke(Result.success(data)) + }, (data, code) => { + console.debug('[AdvancedAPI] startAccelerometer fail') + callback.invoke(Result.fail([data, code])) + }) +} + diff --git a/ohos/AdvancedAPI_OHOS/src/advancedApi/as/device/authenication.js b/ohos/AdvancedAPI_OHOS/src/advancedApi/as/device/authenication.js new file mode 100644 index 0000000000..5d75fc6201 --- /dev/null +++ b/ohos/AdvancedAPI_OHOS/src/advancedApi/as/device/authenication.js @@ -0,0 +1,38 @@ +import Result from '../../../base/util/Result' + +export function startSoterAuthentication (...args) { + console.debug('[AdvancedAPI] start startSoterAuthentication') + const callback = args.pop() + const params = args.pop() + console.debug('[AdvancedAPI] params = %s', JSON.stringify(params)) + const auth = requireAPI('ASAuthentication') + auth.start(params).then(res => { + callback.invoke(Result.success(res)) + }, err => { + callback.invoke(Result.fail(err)) + }) +} + +export function checkIsSupportSoterAuthentication (...args) { + console.debug('[AdvancedAPI] start checkIsSupportSoterAuthentication') + const callback = args.pop() + const auth = requireAPI('ASAuthentication') + auth.getSupportedType().then(res => { + callback.invoke(Result.success(res)) + }, err => { + callback.invoke(Result.fail(err)) + }) +} + +export function checkIsSoterEnrolledInDevice (...args) { + console.debug('[AdvancedAPI] start checkIsSoterEnrolledInDevice') + const callback = args.pop() + const params = args.pop() + console.debug('[AdvancedAPI] params = %s', JSON.stringify(params)) + const auth = requireAPI('ASAuthentication') + auth.isEnrolled(params).then(res => { + callback.invoke(Result.success(res)) + }, err => { + callback.invoke(Result.fail(err)) + }) +} diff --git a/ohos/AdvancedAPI_OHOS/src/advancedApi/as/device/brightness.js b/ohos/AdvancedAPI_OHOS/src/advancedApi/as/device/brightness.js new file mode 100644 index 0000000000..0903585e9b --- /dev/null +++ b/ohos/AdvancedAPI_OHOS/src/advancedApi/as/device/brightness.js @@ -0,0 +1,42 @@ +/** + * Copyright (c) Huawei Technologies Co., Ltd. 2023-2023. All rights reserved. + * Description: advanced as capture screen event api + * Create: 04/12/2023 + * Notes: N/A + */ +import Result from '../../../base/util/Result' + +export function setScreenBrightness(...args) { + const callback = args.pop() + const params = args.pop() + const brightness = requireAPI('ASBrightness') + brightness.setScreenBrightness(params).then(data => { + callback.invoke(Result.success(data)) + }, (data) => { + callback.invoke(Result.fail(data)) + }) +} + +export function getScreenBrightness(...args) { + const callback = args.pop() + const brightness = requireAPI('ASBrightness') + brightness.getScreenBrightness().then(data => { + console.info(`[AdvancedAPI] getScreenBrightness raw = ${data[0].value}`) + const brightValue = data[0].value / 255 + console.info(`[AdvancedAPI] getScreenBrightness = ${brightValue}`) + callback.invoke(Result.success({ value: brightValue })) + }, (data) => { + callback.invoke(Result.fail(data)) + }) +} + +export function setKeepScreenOn(...args) { + const callback = args.pop() + const params = args.pop() + const brightness = requireAPI('ASBrightness') + brightness.asSetKeepScreenOn(params).then(() => { + callback.invoke(Result.success()) + }, () => { + callback.invoke(Result.fail()) + }) +} diff --git a/ohos/AdvancedAPI_OHOS/src/advancedApi/as/device/capture.js b/ohos/AdvancedAPI_OHOS/src/advancedApi/as/device/capture.js new file mode 100644 index 0000000000..30cae9195f --- /dev/null +++ b/ohos/AdvancedAPI_OHOS/src/advancedApi/as/device/capture.js @@ -0,0 +1,21 @@ +/** + * Copyright (c) Huawei Technologies Co., Ltd. 2023-2023. All rights reserved. + * Description: advanced as capture screen event api + * Create: 04/10/2023 + * Notes: N/A + */ +import Result from '../../../base/util/Result' + +export function onUserCaptureScreen(...args) { + const callback = args.pop() + const capture = requireAPI('ASCapture') + + capture.onUserCaptureScreen(callback) +} + +export function offUserCaptureScreen(...args) { + const callback = args.pop() + const capture = requireAPI('ASCapture') + + capture.offUserCaptureScreen(callback) +} \ No newline at end of file diff --git a/ohos/AdvancedAPI_OHOS/src/advancedApi/as/device/compass.js b/ohos/AdvancedAPI_OHOS/src/advancedApi/as/device/compass.js new file mode 100644 index 0000000000..83c0c5f002 --- /dev/null +++ b/ohos/AdvancedAPI_OHOS/src/advancedApi/as/device/compass.js @@ -0,0 +1,62 @@ +/** + * Copyright (c) Huawei Technologies Co., Ltd. 2023-2023. All rights reserved. + * Description: Advanced API compass + * Author: 00430169 + * Create: 23/3/2023 + * Notes: N/A + */ + +import Result from '../../../base/util/Result' + +export function onCompassChange (...args) { + console.debug('[AdvancedAPI] start onCompassChange') + const callback = args.pop() + const compass = requireAPI('ASCompass') + + compass.onCompassChange(callback).then(data => { + console.debug('[AdvancedAPI] onCompassChange success') + }, (data, code) => { + console.debug('[AdvancedAPI] onCompassChange fail errMsg = %o, code = %d', data, code) + }) +} + +export function offCompassChange (...args) { + console.debug('[AdvancedAPI] start offCompassChange') + const callback = args.pop() + const compass = requireAPI('ASCompass') + + compass.offCompassChange(callback).then(data => { + console.debug('[AdvancedAPI] offCompassChange success') + }, (data, code) => { + console.debug('[AdvancedAPI] offCompassChange fail errMsg = %o, code = %d', data, code) + }) +} + +export function startCompass (...args) { + console.debug('[AdvancedAPI] start startCompass') + const callback = args.pop() + const compass = requireAPI('ASCompass') + + compass.startCompass().then(data => { + console.debug('[AdvancedAPI] startCompass success') + callback.invoke(Result.success(data)) + }, (data, code) => { + console.debug('[AdvancedAPI] startCompass fail') + callback.invoke(Result.fail([data, code])) + }) +} + +export function stopCompass (...args) { + console.debug('[AdvancedAPI] start stopCompass') + const callback = args.pop() + const compass = requireAPI('ASCompass') + + compass.stopCompass().then(data => { + console.debug('[AdvancedAPI] stopCompass success') + callback.invoke(Result.success(data)) + }, (data, code) => { + console.debug('[AdvancedAPI] stopCompass fail') + callback.invoke(Result.fail([data, code])) + }) +} + diff --git a/ohos/AdvancedAPI_OHOS/src/advancedApi/as/device/contact.js b/ohos/AdvancedAPI_OHOS/src/advancedApi/as/device/contact.js new file mode 100644 index 0000000000..c456598b1f --- /dev/null +++ b/ohos/AdvancedAPI_OHOS/src/advancedApi/as/device/contact.js @@ -0,0 +1,12 @@ +import Result from '../../../base/util/Result' + +export function addPhoneContact (...args) { + const callback = args.pop() + const params = args.pop() || {} + const contact = requireAPI('ASContact') + contact.addPhoneContact(params).then(data => { + callback.invoke(Result.success(data)) + }, (errData) => { + callback.invoke(Result.fail(errData)) + }) +} diff --git a/ohos/AdvancedAPI_OHOS/src/advancedApi/as/device/gyroscope.js b/ohos/AdvancedAPI_OHOS/src/advancedApi/as/device/gyroscope.js new file mode 100644 index 0000000000..5506f61a08 --- /dev/null +++ b/ohos/AdvancedAPI_OHOS/src/advancedApi/as/device/gyroscope.js @@ -0,0 +1,50 @@ +/** + * Copyright (c) Huawei Technologies Co., Ltd. 2023-2023. All rights reserved. + * Description: Advanced API Gyroscope + * Author: 00430169 + * Create: 23/3/2023 + * Notes: N/A + */ + +import Result from '../../../base/util/Result' + +export function onGyroscopeChange (...args) { + console.debug('[AdvancedAPI] start onGyroscopeChange') + const callback = args.pop() + const gyroscope = requireAPI('ASGyroscope') + + gyroscope.onGyroscopeChange(callback).then(data => { + console.debug('[AdvancedAPI] onGyroscopeChange success') + }, (data, code) => { + console.debug('[AdvancedAPI] onGyroscopeChange fail errMsg = %o, code = %d', data, code) + }) +} + +export function startGyroscope (...args) { + console.debug('[AdvancedAPI] start startCompass') + const callback = args.pop() + const gyroscope = requireAPI('ASGyroscope') + + gyroscope.startGyroscope(args[0]).then(data => { + console.debug('[AdvancedAPI] startCompass success') + callback.invoke(Result.success(data)) + }, (data, code) => { + console.debug('[AdvancedAPI] startCompass fail errMsg = %o, code = %d', data, code) + callback.invoke(Result.fail([data, code])) + }) +} + +export function stopGyroscope (...args) { + console.debug('[AdvancedAPI] start stopGyroscope') + const callback = args.pop() + const gyroscope = requireAPI('ASGyroscope') + + gyroscope.stopGyroscope().then(data => { + console.debug('[AdvancedAPI] stopGyroscope success') + callback.invoke(Result.success(data)) + }, (data, code) => { + console.debug('[AdvancedAPI] stopGyroscope fail errMsg = %o, code = %d', data, code) + callback.invoke(Result.fail([data, code])) + }) +} + diff --git a/ohos/AdvancedAPI_OHOS/src/advancedApi/as/device/system.js b/ohos/AdvancedAPI_OHOS/src/advancedApi/as/device/system.js new file mode 100644 index 0000000000..8c55ee2420 --- /dev/null +++ b/ohos/AdvancedAPI_OHOS/src/advancedApi/as/device/system.js @@ -0,0 +1,57 @@ +import Result from '../../../base/util/Result' + +export function getSystemInfoSync(...args) { + console.debug('[AdvancedAPI] start getSystemInfoSync') + const device = requireAPI('ASDevice') + return device.getSystemInfoSync() +} + +export function getDeviceInfo (...args) { + console.debug('[AdvancedAPI] start getDeviceInfo') + args.pop() + const device = requireAPI('ASDevice') + console.debug('[AdvancedAPI] device.getInfo') + const deviceInfo = device.getDeviceInfo() + return deviceInfo +} + +export function getWindowInfo(...args) { + console.debug('[AdvancedAPI] start getWindowInfo') + args.pop() + const device = requireAPI('ASDevice') + return device.getWindowInfo() +} + +export function getAppBaseInfo(...args) { + console.debug('[AdvancedAPI] start getAppBaseInfo') + args.pop() + const device = requireAPI('ASDevice') + return device.getAppBaseInfo() +} +export function getAppAuthorizeSetting(...args) { + console.debug('[AdvancedAPI] start getAppAuthorizeSetting') + args.pop() + const device = requireAPI('ASDevice') + return device.getAppAuthorizeSetting() +} + +export function getSystemSetting(...args) { + console.debug('[AdvancedAPI] start getSystemSetting') + args.pop() + const device = requireAPI('ASDevice') + console.debug('[AdvancedAPI] device.getSystemSetting') + const systemSetting = device.getSystemSetting() + return systemSetting +} + +export function openAppAuthorizeSetting(...args) { + console.debug('[AdvancedAPI] start getSystemSetting') + const callback = args.pop() + const device = requireAPI('ASDevice') + try { + device.openAppAuthorizeSetting() + callback.invoke(Result.success('success')) + } catch (err) { + callback.invoke(Result.fail(['fail'], 201)) + } +} diff --git a/ohos/AdvancedAPI_OHOS/src/advancedApi/as/device/vibrate.js b/ohos/AdvancedAPI_OHOS/src/advancedApi/as/device/vibrate.js new file mode 100644 index 0000000000..364d31538f --- /dev/null +++ b/ohos/AdvancedAPI_OHOS/src/advancedApi/as/device/vibrate.js @@ -0,0 +1,31 @@ +import Result from '../../../base/util/Result' + +export function vibrate (...args) { + const callback = args.pop() + const vibrator = requireAPI('ASVibrator') + vibrator.vibrate().then((data) => { + callback.invoke(Result.success(data)) + }, (err) => { + callback.invoke(Result.fail(err)) + }) +} + +export function vibrateLong (...args) { + const callback = args.pop() + const vibrator = requireAPI('ASVibrator') + vibrator.vibrateLong().then((data) => { + callback.invoke(Result.success(data)) + }, (err) => { + callback.invoke(Result.fail(err)) + }) +} + +export function vibrateShort (...args) { + const callback = args.pop() + const vibrator = requireAPI('ASVibrator') + vibrator.vibrateShort().then((data) => { + callback.invoke(Result.success(data)) + }, (err) => { + callback.invoke(Result.fail(err)) + }) +} diff --git a/ohos/AdvancedAPI_OHOS/src/advancedApi/as/device/wifi.js b/ohos/AdvancedAPI_OHOS/src/advancedApi/as/device/wifi.js new file mode 100644 index 0000000000..ef60f2eb2d --- /dev/null +++ b/ohos/AdvancedAPI_OHOS/src/advancedApi/as/device/wifi.js @@ -0,0 +1,90 @@ +import Result from '../../../base/util/Result' + +export function startWifi (...args) { + const callback = args.pop() + const wifi = requireAPI('ASWifi') + wifi.startWifi().then(data => { + callback.invoke(Result.success(data)) + }, (err) => { + callback.invoke(Result.fail(err)) + }) +} + +export function stopWifi (...args) { + const callback = args.pop() + const wifi = requireAPI('ASWifi') + wifi.stopWifi().then(data => { + callback.invoke(Result.success(data)) + }, (err) => { + callback.invoke(Result.fail(err)) + }) +} + +export function getConnectedWifi (...args) { + const callback = args.pop() + const params = args.pop() + const wifi = requireAPI('ASWifi') + wifi.getConnectedWifi(params).then(data => { + callback.invoke(Result.success(data)) // data的类型是json对象或者是undefined + }, (err) => { + callback.invoke(Result.fail(err)) + }) +} + +export function getWifiList (...args) { + const callback = args.pop() + const params = args.pop() + const wifi = requireAPI('ASWifi') + wifi.getWifiList(params).then(data => { + callback.invoke(Result.success(data)) + }, err => { + callback.invoke(Result.fail(err)) + }) +} + +export function onGetWifiList (...args) { + const callback = args.pop() + const wifi = requireAPI('ASWifi') + wifi.onGetWifiList(callback) +} + +export function offGetWifiList (...args) { + const callback = args.pop() + const wifi = requireAPI('ASWifi') + wifi.offGetWifiList(callback) +} + +export function connectWifi (...args) { + const callback = args.pop() + const params = args.pop() + const wifi = requireAPI('ASWifi') + wifi.connectWifi(params).then(data => { + callback.invoke(Result.success(data)) + }, err => { + callback.invoke(Result.fail(err)) + }) +} + +export function onWifiConnected (...args) { + const callback = args.pop() + const wifi = requireAPI('ASWifi') + wifi.onWifiConnected(callback) +} + +export function offWifiConnected (...args) { + const callback = args.pop() + const wifi = requireAPI('ASWifi') + wifi.offWifiConnected(callback) +} + +export function onWifiConnectedWithPartialInfo (...args) { + const callback = args.pop() + const wifi = requireAPI('ASWifi') + wifi.onWifiConnectedWithPartialInfo(callback) +} + +export function offWifiConnectedWithPartialInfo (...args) { + const callback = args.pop() + const wifi = requireAPI('ASWifi') + wifi.offWifiConnectedWithPartialInfo(callback) +} diff --git a/ohos/AdvancedAPI_OHOS/src/advancedApi/as/file/file.js b/ohos/AdvancedAPI_OHOS/src/advancedApi/as/file/file.js new file mode 100644 index 0000000000..3065fa456b --- /dev/null +++ b/ohos/AdvancedAPI_OHOS/src/advancedApi/as/file/file.js @@ -0,0 +1,71 @@ +import Result from '../../../base/util/Result' + +export function saveFile (...args) { + const callback = args.pop() + const params = args.pop() || {} + const file = requireAPI('ASFile') + file.saveFile(params).then(data => { + callback.invoke(Result.success(data)) + }).catch(err => { + callback.invoke(Result.fail(err)) + }) +} + +export function getSavedFileList (...args) { + const callback = args.pop() + const file = requireAPI('ASFile') + file.getSavedFileList().then(data => { + callback.invoke(Result.success(data)) + }).catch(err => { + callback.invoke(Result.fail(err)) + }) +} + +export function getSavedFileInfo (...args) { + const callback = args.pop() + const params = args.pop() || {} + const file = requireAPI('ASFile') + file.getSavedFileInfo(params).then(data => { + callback.invoke(Result.success(data)) + }).catch(err => { + callback.invoke(Result.fail(err)) + }) +} + +export function removeSavedFile (...args) { + const callback = args.pop() + const params = args.pop() || {} + const file = requireAPI('ASFile') + file.removeSavedFile(params).then(data => { + callback.invoke(Result.success(data)) + }).catch(err => { + callback.invoke(Result.fail(err)) + }) +} + +export function getFileInfo (...args) { + const callback = args.pop() + const params = args.pop() || {} + const file = requireAPI('ASFile') + file.getFileInfo(params).then(data => { + callback.invoke(Result.success(data)) + }).catch(err => { + callback.invoke(Result.fail(err)) + }) +} + +export function openDocument (...args) { + const callback = args.pop() + const params = args.pop() || {} + const file = requireAPI('ASFile') + file.openDocument(params).then(data => { + callback.invoke(Result.success(data)) + }).catch(err => { + callback.invoke(Result.fail(err)) + }) +} + +export function getFileSystemManager (...args) { + const file = requireAPI('ASFile') + return file.getFileSystemManager() +} diff --git a/ohos/AdvancedAPI_OHOS/src/advancedApi/as/keyboard/keyboard.js b/ohos/AdvancedAPI_OHOS/src/advancedApi/as/keyboard/keyboard.js new file mode 100644 index 0000000000..7b1996b190 --- /dev/null +++ b/ohos/AdvancedAPI_OHOS/src/advancedApi/as/keyboard/keyboard.js @@ -0,0 +1,33 @@ +/** + * Copyright (c) Huawei Technologies Co., Ltd. 2023-2023. All rights reserved. + * Description: advanced as keyboard api + * Create: 04/10/2023 + * Notes: N/A + */ +import Result from '../../../base/util/Result' + +export function hideKeyboard(...args) { + const keyboard = requireAPI('ASKeyboard') + const callback = args.pop() + keyboard.hideKeyboard().then(() => { + console.debug('[AdvancedAPI] hideKeyboard success') + callback.invoke(Result.success()) + }, (err, code) => { + console.debug('[AdvancedAPI] hideKeyboard fail, code: %d, error: %s', code, err) + callback.invoke(Result.fail()) + }) +} + +export function onKeyboardHeightChange(...args) { + const callback = args.pop() + const keyboard = requireAPI('ASKeyboard') + + keyboard.onKeyboardHeightChange(callback) +} + +export function offKeyboardHeightChange(...args) { + const callback = args.pop() + const keyboard = requireAPI('ASKeyboard') + + keyboard.offKeyboardHeightChange(callback) +} diff --git a/ohos/AdvancedAPI_OHOS/src/advancedApi/as/location/location.js b/ohos/AdvancedAPI_OHOS/src/advancedApi/as/location/location.js new file mode 100644 index 0000000000..df2b13f4b1 --- /dev/null +++ b/ohos/AdvancedAPI_OHOS/src/advancedApi/as/location/location.js @@ -0,0 +1,87 @@ +import Result from '../../../base/util/Result' + +export function getLocation (...args) { + console.debug('[AdvancedAPI] start getLocation') + const callback = args.pop() + const params = args.pop() + const geolocation = requireAPI('ASLocation') + console.debug('[AdvancedAPI] geolocation.getLocation') + geolocation.getLocation(params).then(data => { + console.debug('[AdvancedAPI] geolocation.getLocation success') + callback.invoke(Result.success(data)) + }, (err, code) => { + console.debug('[AdvancedAPI] geolocation.getLocation fail') + callback.invoke(Result.fail(err)) + }) +} +export function onLocationChange(...args) { + console.debug('[AdvancedAPI] start onLocationChange') + const callback = args.pop() + const geolocation = requireAPI('ASLocation') + geolocation.onLocationChange(callback) +} + +export function offLocationChange(...args) { + console.debug('[AdvancedAPI] start offLocationChange') + const callback = args.pop() + const geolocation = requireAPI('ASLocation') + geolocation.offLocationChange(callback) + geolocation.getLocation({ timeout: 5000, coordType: 'wgs86' }).then(data => { + console.debug('[AdvancedAPI] geolocation.offLocationChange callback') + callback.invokeAndKeepAlive(Result.success(data)) + }, err => { + callback.invokeAndKeepAlive(Result.fail([err[0][0], err[0][1]])) + }) +} +export function onLocationChangeError(...args) { + console.debug('[AdvancedAPI] start onLocationChangeError') + const callback = args.pop() + const geolocation = requireAPI('ASLocation') + geolocation.onLocationChangeError(data => { + console.debug('[AdvancedAPI] geolocation.onLocationChange success') + callback.invokeAndKeepAlive(Result.callback(data)) + }) +} +export function offLocationChangeError(...args) { + console.debug('[AdvancedAPI] start offLocationChangeError') + const callback = args.pop() + const geolocation = requireAPI('ASLocation') + geolocation.offLocationChangeError() + callback.invoke(Result.success()) +} +export function startLocationUpdate(...args) { + console.debug('[AdvancedAPI] start startLocationUpdate') + const callback = args.pop() + const geolocation = requireAPI('ASLocation') + geolocation.startLocationUpdate().then(data => { + console.debug('[AdvancedAPI] geolocation.startLocationUpdate success') + callback.invoke(Result.success(data)) + }, (err, code) => { + console.debug('[AdvancedAPI] geolocation.startLocationUpdate fail') + callback.invoke(Result.fail([err[0][0], err[0][1]])) + }) +} +export function startLocationUpdateBackground(...args) { + console.debug('[AdvancedAPI] start startLocationUpdateBackground') + const callback = args.pop() + const geolocation = requireAPI('ASLocation') + geolocation.startLocationUpdateBackground().then(data => { + console.debug('[AdvancedAPI] geolocation.startLocationUpdateBackground success') + callback.invoke(Result.success(data)) + }, (err, code) => { + console.debug('[AdvancedAPI] geolocation.startLocationUpdateBackground fail') + callback.invoke(Result.fail([err[0][0], err[0][1]])) + }) +} +export function stopLocationUpdate(...args) { + console.debug('[AdvancedAPI] start stopLocationUpdate') + const callback = args.pop() + const geolocation = requireAPI('ASLocation') + geolocation.stopLocationUpdate(callback).then(data => { + console.debug('[AdvancedAPI] geolocation.stopLocationUpdate success') + callback.invoke(Result.success(data)) + }, (err, code) => { + console.debug('[AdvancedAPI] geolocation.stopLocationUpdate fail') + callback.invoke(Result.fail([err[0][0], err[0][1]])) + }) +} diff --git a/ohos/AdvancedAPI_OHOS/src/advancedApi/as/media/audio.js b/ohos/AdvancedAPI_OHOS/src/advancedApi/as/media/audio.js new file mode 100644 index 0000000000..55c4be173e --- /dev/null +++ b/ohos/AdvancedAPI_OHOS/src/advancedApi/as/media/audio.js @@ -0,0 +1,5 @@ +export function createInnerAudioContext() { + console.debug('[AdvancedAPI] start createInnerAudioContext') + const audio = requireAPI('ASAudio') + return audio.createInnerAudioContext() +} diff --git a/ohos/AdvancedAPI_OHOS/src/advancedApi/as/media/image.js b/ohos/AdvancedAPI_OHOS/src/advancedApi/as/media/image.js new file mode 100644 index 0000000000..21c1e0e6b8 --- /dev/null +++ b/ohos/AdvancedAPI_OHOS/src/advancedApi/as/media/image.js @@ -0,0 +1,59 @@ +import Result from '../../../base/util/Result' + +export function chooseImage (...args) { + console.debug('[AdvancedAPI] start chooseImage') + const callback = args.pop() + const image = requireAPI('ASImage') + const params = args[0] + image.chooseImage(params).then( + res => { + callback.invoke(Result.success(res)) + }, + err => { + callback.invoke(Result.fail(err)) + } + ) +} + +export function getImageInfo(...args) { + console.debug('[AdvancedAPI] start getImageInfo') + const callback = args.pop() + const image = requireAPI('ASImage') + const params = args[0] + image.getImageInfo(params).then( + res => { + callback.invoke(Result.success(res)) + }, + err => { + callback.invoke(Result.fail(err)) + } + ) +} +export function saveImageToPhotosAlbum(...args) { + console.debug('[AdvancedAPI] start saveImageToPhotosAlbum') + const callback = args.pop() + const image = requireAPI('ASImage') + const params = args[0] + image.saveImageToPhotosAlbum(params).then( + res => { + callback.invoke(Result.success(res)) + }, + err => { + callback.invoke(Result.fail(err)) + } + ) +} +export function compressImage(...args) { + console.debug('[AdvancedAPI] start compressImage') + const callback = args.pop() + const image = requireAPI('ASImage') + const params = args[0] + image.compressImage(params).then( + res => { + callback.invoke(Result.success(res)) + }, + err => { + callback.invoke(Result.fail(err)) + } + ) +} diff --git a/ohos/AdvancedAPI_OHOS/src/advancedApi/as/media/video.js b/ohos/AdvancedAPI_OHOS/src/advancedApi/as/media/video.js new file mode 100644 index 0000000000..12b84b9431 --- /dev/null +++ b/ohos/AdvancedAPI_OHOS/src/advancedApi/as/media/video.js @@ -0,0 +1,31 @@ +import Result from '../../../base/util/Result' + +export function saveVideoToPhotosAlbum(...args) { + console.debug('[AdvancedAPI] start saveVideoToPhotosAlbum') + const callback = args.pop() + const video = requireAPI('ASVideo') + const params = args[0] + video.saveVideoToPhotosAlbum(params).then( + res => { + callback.invoke(Result.success(res)) + }, + err => { + callback.invoke(Result.fail(err)) + } + ) +} + +export function getVideoInfo(...args) { + console.debug('[AdvancedAPI] start getVideoInfo') + const callback = args.pop() + const video = requireAPI('ASVideo') + const params = args[0] + video.getVideoInfo(params).then( + res => { + callback.invoke(Result.success(res)) + }, + err => { + callback.invoke(Result.fail(err)) + } + ) +} diff --git a/ohos/AdvancedAPI_OHOS/src/advancedApi/as/request/request.js b/ohos/AdvancedAPI_OHOS/src/advancedApi/as/request/request.js new file mode 100644 index 0000000000..36eba74348 --- /dev/null +++ b/ohos/AdvancedAPI_OHOS/src/advancedApi/as/request/request.js @@ -0,0 +1,61 @@ +/** + * Copyright (c) Huawei Technologies Co., Ltd. 2023-2023. All rights reserved. + * Description: advanced as request api + * Create: 04/01/2023 + * Notes: N/A + */ +import Result from '../../../base/util/Result' + +export function request(...args) { + const callback = args.pop() + const obj = args.pop() + const http = requireAPI('ASRequest') + console.debug('[AdvancedAPI] request') + + const task = http.request(obj) + // if success / fail / complete, return requestTask otherwise return Promise + if (obj && !obj.success && !obj.fail && !obj.complete) { + callback.invoke(Result.success(task)) + return + } + if (!obj) { + callback.invoke(Result.fail(['illegal params', -1])) + } + return task +} + +export function uploadFile(...args) { + const callback = args.pop() + const obj = args.pop() + const http = requireAPI('ASRequest') + console.debug('[AdvancedAPI] uploadFile') + + const task = http.uploadFile(obj) + // if success / fail / complete, return uploadTask otherwise return Promise + if (obj && !obj.success && !obj.fail && !obj.complete) { + callback.invoke(Result.success(task)) + return + } + if (!obj) { + callback.invoke(Result.fail(['illegal params', -1])) + } + return task +} + +export function downloadFile(...args) { + const callback = args.pop() + const obj = args.pop() + const http = requireAPI('ASRequest') + console.debug('[AdvancedAPI] downloadFile') + + const task = http.downloadFile(obj) + // if success / fail / complete, return downloadTask otherwise return Promise + if (obj && !obj.success && !obj.fail && !obj.complete) { + callback.invoke(Result.success(task)) + return + } + if (!obj) { + callback.invoke(Result.fail(['illegal params', -1])) + } + return task +} diff --git a/ohos/AdvancedAPI_OHOS/src/advancedApi/as/router/navigate.js b/ohos/AdvancedAPI_OHOS/src/advancedApi/as/router/navigate.js new file mode 100644 index 0000000000..fc0e05743d --- /dev/null +++ b/ohos/AdvancedAPI_OHOS/src/advancedApi/as/router/navigate.js @@ -0,0 +1,34 @@ +import Result from '../../../base/util/Result' + +export function navigateTo (...args) { + const callback = args.pop() + const params = args.pop() || {} + const router = requireAPI('ASRouter') + router.navigateTo(params).then(data => { + callback.invoke(Result.success(data)) + }, (err) => { + callback.invoke(Result.fail(err)) + }) +} + +export function redirectTo (...args) { + const callback = args.pop() + const params = args.pop() || {} + const router = requireAPI('ASRouter') + router.redirectTo(params).then(data => { + callback.invoke(Result.success(data)) + }, (err) => { + callback.invoke(Result.fail(err)) + }) +} + +export function navigateBack (...args) { + const callback = args.pop() + const params = args.pop() || {} + const router = requireAPI('ASRouter') + router.navigateBack(params).then(data => { + callback.invoke(Result.success(data)) + }, (err) => { + callback.invoke(Result.fail(err)) + }) +} diff --git a/ohos/AdvancedAPI_OHOS/src/advancedApi/as/scan/scan.js b/ohos/AdvancedAPI_OHOS/src/advancedApi/as/scan/scan.js new file mode 100644 index 0000000000..577bb0aec0 --- /dev/null +++ b/ohos/AdvancedAPI_OHOS/src/advancedApi/as/scan/scan.js @@ -0,0 +1,15 @@ +import Result from '../../../base/util/Result' +export function scanCode (...args) { + console.debug('[AdvancedAPI] start scanCode') + const callback = args.pop() + const params = args[0] + const scan = requireAPI('ASScan') + scan.scanCode(params).then( + res => { + callback.invoke(Result.success(res)) + }, + err => { + callback.invoke(Result.fail(err)) + } + ) +} diff --git a/ohos/AdvancedAPI_OHOS/src/advancedApi/as/telephony/telephony.js b/ohos/AdvancedAPI_OHOS/src/advancedApi/as/telephony/telephony.js new file mode 100644 index 0000000000..8b43a2af25 --- /dev/null +++ b/ohos/AdvancedAPI_OHOS/src/advancedApi/as/telephony/telephony.js @@ -0,0 +1,12 @@ +import Result from '../../../base/util/Result' +export function makePhoneCall (...args) { + const callback = args.pop() + const number = args.pop() + const phone = requireAPI('ASPhone') + phone.makePhoneCall(number).then(() => { + callback.invoke(Result.success()) + }, (err) => { + console.error(`[AdvancedAPI] start makePhoneCall fail`) + callback.invoke(Result.fail([err, -1])) + }) +} diff --git a/ohos/AdvancedAPI_OHOS/src/advancedApi/callback/JSCallback.js b/ohos/AdvancedAPI_OHOS/src/advancedApi/callback/JSCallback.js new file mode 100644 index 0000000000..1362bae96b --- /dev/null +++ b/ohos/AdvancedAPI_OHOS/src/advancedApi/callback/JSCallback.js @@ -0,0 +1,31 @@ +import callbackManager from './index' + +export default class JSCallback { + constructor (options) { + this.id = options.id + this._valid = true + } + + invoke (data) { + if (this._valid) { + callbackManager.consume(this.id, data, data.ifKeepAlive) + } else { + console.error(`[AdvancedAPI] callback ${this.id} had be destroyed.`) + } + } + + invokeAndKeepAlive (data) { + if (this._valid) { + callbackManager.consume(this.id, data, true) + } else { + console.error(`[AdvancedAPI] callback ${this.id} had be destroyed.`) + } + } + + destroy () { + this.id = undefined + this._valid = false + } +} + +export const jsCallbackMap = new Map() diff --git a/ohos/AdvancedAPI_OHOS/src/advancedApi/callback/callback-intercept.js b/ohos/AdvancedAPI_OHOS/src/advancedApi/callback/callback-intercept.js new file mode 100644 index 0000000000..266586bae5 --- /dev/null +++ b/ohos/AdvancedAPI_OHOS/src/advancedApi/callback/callback-intercept.js @@ -0,0 +1,153 @@ +import callbackManager from './index' + +// promise化 +export function interceptCallback (args, moduleName, needPromise = true, needCallback = true) { + if (!needPromise + && (args.length === 0 || !needCallback)) { + return { args } + } + + const first = args[0] + const callbacks = {} + let hasProperty = false + + if ( + typeof first === 'object' + && Object.prototype.toString.call(first).toLowerCase() === '[object object]' + && args.length === 1 + ) { + for (const key in first) { + const value = first[key] + if (typeof value === 'function') { + callbacks[key] = value + } else { + hasProperty = true + } + } + } else { + hasProperty = true + } + + // 参数是一个方法 + if (typeof first === 'function') { + needPromise = false + if (!first.isConnected) { + const cb = msg => { + first.apply(null, msg.arguments) + } + cb.originFn = first + first.cb = cb + args[0] = cb + } else if (first.cb) { + args[0] = first.cb.id + } + } + + let promise + const cbLength = Object.keys(callbacks).length + if (needPromise) { + if (cbLength <= 0) { + class PromiseRef { + constructor () { + this.promise = new Promise((resolve, reject) => { + this.reject = reject + this.resolve = resolve + }) + } + } + promise = new PromiseRef() + } + } + if (cbLength > 0 || promise) { + const cb = msg => { + let f = callbacks[msg.method] + advancedResult(moduleName, msg) + const methodArgs = triggerMethodIntercept(moduleName, msg.method, msg.arguments) || msg.arguments + if (f !== undefined) { + f.apply(null, methodArgs) + } + const { ignoreComplete = false } = msg + if (!ignoreComplete) { + const completeArgs = triggerMethodIntercept(moduleName, 'complete', msg.arguments) || msg.arguments + f = callbacks['complete'] + if (f !== undefined) { + f.apply(null, completeArgs) + } + } + if (promise) { + const cbArgs = msg.arguments + const data = cbArgs && cbArgs.length > 0 ? cbArgs[0] : undefined + if (msg.method === 'success' || msg.method === 'callback') { + promise.resolve(data) + } else { + promise.reject(data) + } + } + } + + cb.__onlyPromise = cbLength <= 0 + + if (hasProperty) { + args.push(cb) + } else { + args = [cb] + } + } + + if (first && !first.isConnected || promise) { + args = args.map(arg => { + return normalize(arg) + }) + } + if (first && first.cb) { + first.isConnected = true + } + + return { args, promise, needPromise } +} + +function normalize (v) { + if (typeof v === 'function') { + const id = callbackManager.add(v) + v.id = id + return id + } + return v +} + +/** + * 封装接口的返回对象 + * @return {object} { errMsg, errCode, ... } + */ +function advancedResult (moduleName, msg) { + if (msg.method === 'success') { + if (!msg.arguments[0] || typeof msg.arguments[0] !== 'object') { + msg.arguments[0] = {} + } + const data = msg.arguments[0] + if (data.errMsg === undefined) { + data.errMsg = `${moduleName}:ok` + } + if (data.errCode === undefined) { + data.errCode = 0 + } + } else if (msg.method === 'fail') { + const originArgs = msg.arguments || [] + msg.arguments = [{ + moduleName: `${moduleName}`, + errMsg: `${moduleName}:fail:${originArgs.shift()}`, + errCode: originArgs.shift(), + grantStatus: originArgs.shift(), + dialogShownResults: originArgs.shift() + }] + } +} + +function triggerMethodIntercept (moduleName, method, args) { + const interceptor = requireAPI('ASInterceptor') + const intercepterMethod = interceptor[method] + if (typeof intercepterMethod === 'function') { + const methodArgs = intercepterMethod.call(interceptor, moduleName, args) + return methodArgs + } +} diff --git a/ohos/AdvancedAPI_OHOS/src/advancedApi/callback/index.js b/ohos/AdvancedAPI_OHOS/src/advancedApi/callback/index.js new file mode 100644 index 0000000000..31a1c0ebd7 --- /dev/null +++ b/ohos/AdvancedAPI_OHOS/src/advancedApi/callback/index.js @@ -0,0 +1,33 @@ +class CallbackManager { + constructor (cb) { + this.lastCallbackId = 0 + this.callbacks = [] + } + + add (callback) { + this.lastCallbackId++ + this.callbacks[this.lastCallbackId] = callback + callback.__callbackId = this.lastCallbackId + return this.lastCallbackId + } + + consume (callbackId, data, ifKeepAlive) { + const callback = this.callbacks[callbackId] + if (typeof ifKeepAlive === 'undefined' || ifKeepAlive === false) { + this.callbacks[callbackId] = undefined + } else { + callback.isKeepAlive = true + } + if (typeof callback === 'function') { + return callback(data) + } + return new Error(`invalid callback id "${callbackId}"`) + } + + close () { + this.callbacks = this.callbacks.map(cb => undefined) + } +} + +const callbackManager = new CallbackManager() +export default callbackManager diff --git a/ohos/AdvancedAPI_OHOS/src/advancedApi/index.js b/ohos/AdvancedAPI_OHOS/src/advancedApi/index.js new file mode 100644 index 0000000000..daebc67b9f --- /dev/null +++ b/ohos/AdvancedAPI_OHOS/src/advancedApi/index.js @@ -0,0 +1,30 @@ +import { initContextOnStageModel } from '../base/bridge/abilityBase' +import { requireAPI } from './module/index' +import as, { createAs } from './module/interface' +import media from '@ohos.multimedia.media' +import bundleManager from '@ohos.bundle.bundleManager' + +const AdvancedApi = { + init: function (context, windowClass) { + if (globalThis.as && globalThis.requireAPI) { + return + } + console.debug('[AdvancedAPI] init') + globalThis.as = as + globalThis.requireAPI = requireAPI + globalThis.isStageModel = true + globalThis.abilityContext = context + media.createAVRecorder().then( + (recorder) => { + globalThis.commonAvRecorder = recorder + } + ) + const flags = bundleManager.BundleFlag.GET_BUNDLE_INFO_WITH_SIGNATURE_INFO | bundleManager.BundleFlag.GET_BUNDLE_INFO_WITH_APPLICATION + globalThis.bundleInfoForSelf = bundleManager.getBundleInfoForSelfSync(flags) + globalThis.lastWindow = windowClass + initContextOnStageModel(context) + } +} + +export default AdvancedApi +export { as, createAs } diff --git a/ohos/AdvancedAPI_OHOS/src/advancedApi/module/ASAccelerometer/index.js b/ohos/AdvancedAPI_OHOS/src/advancedApi/module/ASAccelerometer/index.js new file mode 100644 index 0000000000..850e0aeca7 --- /dev/null +++ b/ohos/AdvancedAPI_OHOS/src/advancedApi/module/ASAccelerometer/index.js @@ -0,0 +1,99 @@ +/** + * Copyright (c) Huawei Technologies Co., Ltd. 2023-2023. All rights reserved. + * Description: Advanced API Storage + * Author: 00430169 + * Create: 6/4/2023 + * Notes: N/A + */ + +import { OhosSensorBase } from '../../../base/bridge/sensorBase' +import { ErrorCode } from '../../../base/util/ErrorCode' + +const intervalType = [ + { label: 'game', value: 20000000 }, + { label: 'ui', value: 60000000 }, + { label: 'normal', value: 200000000 } +] + +export default class ASAccelerometer { + constructor () { + this.callBackSet = new Set() + this.defaultInterval = 'normal' + } + + onAccelerometerChange (callback) { + return new Promise((resolve, reject) => { + if (typeof callback !== 'function') { + reject('param is invalid.', ErrorCode.PARAMETER_ERROR) + return + } + if (this.callBackSet.has(callback)) { + reject('param is invalid.', ErrorCode.PARAMETER_ERROR) + } else { + this.callBackSet.add(callback) + const value = intervalType.find(i => i.label === this.defaultInterval).value + OhosSensorBase.ohosSubscribeAccelerometer({ interval: value, callback: (data) => { + const res = { + x: data.x, + y: data.y, + z: data.z + } + for (const cb of this.callBackSet.keys()) { + cb(res) + } + } }) + resolve() + } + }) + } + + offAccelerometerChange (callback) { + return new Promise((resolve, reject) => { + if (typeof callback !== 'function') { + this.callBackSet.clear() + OhosSensorBase.ohosUnsubscribeAccelerometer() + resolve() + return + } + if (!this.callBackSet.has(callback)) { + reject('param is invalid.', ErrorCode.COMMON_ERROR) + } else { + this.callBackSet.delete(callback) + if (this.callBackSet.size === 0) { + OhosSensorBase.ohosUnsubscribeAccelerometer() + } + resolve() + } + }) + } + + startAccelerometer (object) { + return new Promise((resolve, reject) => { + let value = intervalType.find(i => i.label === this.defaultInterval).value + if (object.interval && (typeof object.interval === 'string')) { + const target = intervalType.find(i => i.label === object.interval) + if (target) { + value = target.value + } + } + OhosSensorBase.ohosSubscribeAccelerometer({ interval: value, callback: (data) => { + const res = { + x: data.x, + y: data.y, + z: data.z + } + for (const cb of this.callBackSet.keys()) { + cb(res) + } + } }) + resolve() + }) + } + + stopAccelerometer () { + return new Promise((resolve, reject) => { + OhosSensorBase.ohosUnsubscribeAccelerometer() + resolve() + }) + } +} diff --git a/ohos/AdvancedAPI_OHOS/src/advancedApi/module/ASAudio/index.js b/ohos/AdvancedAPI_OHOS/src/advancedApi/module/ASAudio/index.js new file mode 100644 index 0000000000..ab00704ce9 --- /dev/null +++ b/ohos/AdvancedAPI_OHOS/src/advancedApi/module/ASAudio/index.js @@ -0,0 +1,552 @@ +import media from '@ohos.multimedia.media' +import audio from '@ohos.multimedia.audio' +import fs from '@ohos.file.fs' +import { MediaLibraryBase } from '../../../base/bridge/mediaLibraryBase' +import { switchInternalToHapSandBox } from '../../util/index' + +// 音频播放状态 +const StateType = { + // 音频播放空闲 + IDLE: 'idle', + // 设置播放源 + INITIALIZED: 'initialized', + // 准备播放 + PREPARED: 'prepared', + // 音频正在播放 + PLAYING: 'playing', + // 音频暂停播放 + PAUSED: 'paused', + // 音频播放完成 + COMPLETED: 'completed', + // 音频停止播放 + STOPPED: 'stopped', + // 音频释放 + RELEASED: 'released', + // 错误状态 + ERROR: 'error', +} + +export default class ASAudio { + createInnerAudioContext() { + return new InnerAudioContext() + } +} + +class InnerAudioContext { + count = 0 + stopFlag = false + + constructor() { + this.tempSrc = '' + this.startTimeS = 0 + this.autoplayS = false + this.playbackRateS = 1 + this.bufferedS = 0 + this.volumeS = 1 + this.tempLoop = false + this.onCanplayCallback = null + this.onPlayCallback = null + this.onPauseCallback = null + this.onStopCallback = null + this.onEndedCallback = null + this.onTimeUpdateCallback = null + this.onErrorCallback = null + this.onWaitingCallback = null + this.onSeekedCallback = null + this.onSeekingCallback = null + this.init() + } + + async init() { + this.avPlayer = await media.createAVPlayer() + + // seek操作结果回调函数 + this.avPlayer.on('seekDone', (seekDoneTime) => { + console.info(`AVPlayer seek succeeded, seek time is ${seekDoneTime}`) + if (this.onSeekedCallback) { + this.onSeekedCallback({}) + } + }) + + // error回调监听函数,当avPlayer在操作过程中出现错误时调用reset接口触发重置流程 + this.avPlayer.on('error', (err) => { + console.error(`Invoke avPlayer failed, code is ${err.code}, message is ${err.message}`) + this.avPlayer.reset() // 调用reset重置资源,触发idle状态 + if (this.onErrorCallback) { + this.onErrorCallback(err) + } + }) + // 状态机变化回调函数 + this.avPlayer.on('stateChange', async (state, reason) => { + switch (state) { + case 'idle': // 成功调用reset接口后触发该状态机上报 + console.info('AVPlayer state idle called.') + if (this.stopFlag) { + this.avPlayer.url = this.tempSrc + this.stopFlag = false + } + break + case 'initialized': // avplayer 设置播放源后触发该状态上报 + console.info('AVPlayerstate initialized called.') + this.avPlayer.prepare().then(() => { + console.info('AVPlayer prepare succeeded.') + if (this.onCanplayCallback) { + this.onCanplayCallback({}) + } + }, (err) => { + console.error(`Invoke prepare failed, code is ${err.code}, message is ${err.message}`) + }) + break + case 'prepared': // prepare调用成功后上报该状态机 + console.info('AVPlayer state prepared called.') + if (this.count === 0 && this.autoplayS) { + this.avPlayer.play() + if (this.onPlayCallback) { + this.onPlayCallback({}) + } + if (this.startTimeS) { + if (this.onSeekingCallback) { + this.onSeekingCallback({}) + } + this.avPlayer.seek(this.startTimeS) + } + } + this.count++ + + // 处理属性 + this.avPlayer.loop = this.tempLoop + this.avPlayer.setVolume(this.volumeS) + this.avPlayer.setSpeed(this.playbackRateS) + break + case 'playing': // play成功调用后触发该状态机上报 + console.info('AVPlayer state playing called.') + + // 处理属性 + this.avPlayer.loop = this.tempLoop + this.avPlayer.setVolume(this.volumeS) + this.avPlayer.setSpeed(this.playbackRateS) + break + case 'paused': // pause成功调用后触发该状态机上报 + console.info('AVPlayer state paused called.') + + // 处理属性 + this.avPlayer.loop = this.tempLoop + this.avPlayer.setVolume(this.volumeS) + this.avPlayer.setSpeed(this.playbackRateS) + break + case 'completed': // 播放结束后触发该状态机上报 + console.info('AVPlayer state completed called.') + if (this.onEndedCallback) { + this.onEndedCallback({}) + } + + // 处理属性 + this.avPlayer.loop = this.tempLoop + this.avPlayer.setVolume(this.volumeS) + this.avPlayer.setSpeed(this.playbackRateS) + break + case 'stopped': // stop接口成功调用后触发该状态机上报 + console.info('AVPlayer state stopped called.') + this.avPlayer.reset() // 调用reset接口初始化avplayer状态 + this.stopFlag = true + break + case 'released': + console.info('AVPlayer state released called.') + break + default: + console.info('AVPlayer state unknown called.') + break + } + }) + + this.avPlayer.on('timeUpdate', res => { + if (this.onTimeUpdateCallback) { + this.onTimeUpdateCallback(res / 1000) + } + }) + + this.avPlayer.on('bufferingUpdate', (infoType, value) => { + console.info(`[AdvancedAPI] avPlayer bufferingUpdate ${infoType} ${value}`) + if (infoType === 3 && value !== 0) { + this.bufferedS = value + // 为缓存百分比 + if ((this.avPlayer.currentTime / 1000) >= (this.avPlayer.duration * value / 100000) && this.onWaitingCallback) { + this.onWaitingCallback({}) + } + } + }) + + this.avPlayer.on('audioInterrupt', (InterruptEvent) => { + console.info('[AdvancedAPI] audioInterrupt:' + JSON.stringify(InterruptEvent)) + if (InterruptEvent.hintType === audio.InterruptHint.INTERRUPT_HINT_PAUSE) { + this.avPlayer.pause() + if (this.onPauseCallback) { + this.onPauseCallback({}) + } + } + }) + + this.avPlayer.on('endOfStream', () => { + console.info('[AdvancedAPI] rePlay:endOfStream success') + if (this.avPlayer.loop) { + this.avPlayer.play() + if (this.startTimeS) { + if (this.onSeekingCallback) { + this.onSeekingCallback({}) + } + this.avPlayer.seek(this.startTimeS) + } + } + }) + } + + get duration() { + if (!this.avPlayer) { + console.error(`[AdvancedAPI] avPlayer is not exist, get duration fail`) + return 0 + } + return this.avPlayer.duration / 1000 + } + + get currentTime() { + if (!this.avPlayer) { + console.error(`[AdvancedAPI] avPlayer is not exist, get currentTime fail`) + return 0 + } + return this.avPlayer.currentTime / 1000 + } + + get paused() { + if (!this.avPlayer) { + console.error(`[AdvancedAPI] avPlayer is not exist, get paused fail`) + return true + } + return this.avPlayer.state === StateType.PAUSED + } + + get loop() { + return this.tempLoop + } + + set loop(value) { + if (typeof (value) !== 'boolean') { + console.error(`[AdvancedAPI] loop: ${value} is invalid`) + return + } + this.tempLoop = value + + if (this.avPlayer && [StateType.PREPARED, StateType.PLAYING, StateType.PAUSED, StateType.COMPLETED].includes(this.avPlayer.state)) { + console.info('current state is ' + this.avPlayer.state + ' can set loop') + this.avPlayer.loop = value + } + } + + get volume() { + return this.volumeS + } + + set volume(value) { + if (typeof (value) !== 'number') { + console.error(`[AdvancedAPI] volume: ${value} is invalid`) + return + } + this.volumeS = value + if (this.avPlayer && [StateType.PREPARED, StateType.PLAYING, StateType.PAUSED, StateType.COMPLETED].includes(this.avPlayer.state)) { + console.info('current state is ' + this.avPlayer.state + ' can set volume') + this.avPlayer.setVolume(value) + } + } + + get autoplay() { + return this.autoplayS + } + + set autoplay(flag) { + if (typeof (flag) !== 'boolean') { + console.error(`[AdvancedAPI] autoplay: ${flag} is invalid`) + return + } + this.autoplayS = flag + } + + get startTime() { + return this.startTimeS / 1000 + } + + set startTime(time) { + if (typeof (time) !== 'number') { + console.error(`[AdvancedAPI] startTIme: ${time} is invalid`) + return + } + this.startTimeS = time * 1000 + } + + get src() { + if (!this.avPlayer) { + console.error(`[AdvancedAPI] avPlayer is not exist, get src fail`) + return '' + } + return this.avPlayer.url + } + + set src(value) { + if (typeof (value) !== 'string') { + console.error(`[AdvancedAPI] src: ${value} is invalid`) + return + } + if (!this.avPlayer) { + console.error(`[AdvancedAPI] avPlayer is not exist, set src fail`) + return + } + if (!value || !(value.startsWith('http:') || value.startsWith('https:') + || value.startsWith('datashare:') || value.startsWith('internal://'))) { + console.error(`[AdvancedAPI] src: ${value} is invalid`) + return + } + if (this.avPlayer.state !== StateType.IDLE) { + console.error('current state is ' + this.avPlayer.state + ' can not set url') + return + } + let path + if (value.startsWith('http:') || value.startsWith('https:')) { + path = value + } else if (value.startsWith('internal://')) { + try { + const uri = switchInternalToHapSandBox(value) + const file = fs.openSync(uri, fs.OpenMode.READ_ONLY) + const fd = file.fd + path = `fd://${fd}` + } catch (error) { + console.info(`${JSON.stringify(error)}`) + } + } else if (value.startsWith('datashare:')) { + try { + const media = MediaLibraryBase.getMedia() + const fileKeyObj = MediaLibraryBase.getFileKey() + const audioType = MediaLibraryBase.getMediaType('AUDIO') + const audiosfetchOp = { + selections: fileKeyObj.MEDIA_TYPE + '= ?', + selectionArgs: [audioType.toString()], + uri: value, + } + media.getFileAssets(audiosfetchOp).then(fileResult => { + fileResult.getFirstObject().then(asset => { + MediaLibraryBase.getFd(asset).then(fd => { + path = `fd://${fd}` + if (this.avPlayer.url && path !== this.avPlayer.url) { + this.avPlayer.reset() + } + this.avPlayer.url = path + }) + }) + }) + return + } catch (error) { + console.error(`[AdvancedAPI] src: ${value} is invalid`) + return + } + } + if (this.avPlayer.url && path !== this.avPlayer.url) { + this.avPlayer.reset() + } + this.avPlayer.url = path + this.tempSrc = path + } + + get buffered() { + if (!this.avPlayer) { + console.error(`[AdvancedAPI] avPlayer is not exist, get buffered fail`) + return 0 + } + return this.avPlayer.duration * this.bufferedS / 100000 + } + + get playbackRate() { + return this.playbackRateS + } + + set playbackRate(value) { + if (typeof (value) !== 'number') { + console.error(`[AdvancedAPI] speed: ${value} is invalid`) + return + } + let rate + if (value <= 0.75) { + rate = media.PlaybackSpeed.SPEED_FORWARD_0_75_X + } else if (value > 0.75 && value <= 1) { + rate = media.PlaybackSpeed.SPEED_FORWARD_1_00_X + } else if (value > 1 && value <= 1.25) { + rate = media.PlaybackSpeed.SPEED_FORWARD_1_25_X + } else if (value > 1.25 && value <= 1.75) { + rate = media.PlaybackSpeed.SPEED_FORWARD_1_75_X + } else { + rate = media.PlaybackSpeed.SPEED_FORWARD_2_00_X + } + this.playbackRateS = rate + if (this.avPlayer && [StateType.PREPARED, StateType.PLAYING, StateType.PAUSED, StateType.COMPLETED].includes(this.avPlayer.state)) { + console.info('current state is ' + this.avPlayer.state + ' can not set playbackRate') + this.avPlayer.setSpeed(rate) + } + } + + play() { + if (!this.avPlayer) { + console.error(`[AdvancedAPI] avPlayer is not exist, play fail`) + return + } + if (![StateType.PREPARED, StateType.PAUSED, StateType.COMPLETED].includes(this.avPlayer.state)) { + console.error('current state is ' + this.avPlayer.state + ' can not play') + return + } + if (this.tempSrc && this.avPlayer.url === '') { + this.avPlayer.url = this.tempSrc + } + this.avPlayer.play() + if (this.onPlayCallback) { + this.onPlayCallback({}) + } + } + + pause() { + if (!this.avPlayer) { + console.error(`[AdvancedAPI] avPlayer is not exist, pause fail`) + return + } + const state = this.avPlayer.state + if (StateType.PLAYING !== state) { + console.error('current state is ' + this.avPlayer.state + 'can not pause') + return + } + this.avPlayer.pause() + if (this.onPauseCallback) { + this.onPauseCallback({}) + } + } + + stop() { + if (!this.avPlayer) { + console.error(`[AdvancedAPI] avPlayer is not exist, stop fail`) + return + } + // prepared/playing/paused/complete + if (![StateType.PREPARED, StateType.PLAYING, StateType.PAUSED, StateType.COMPLETED].includes(this.avPlayer.state)) { + console.error('current state is ' + this.avPlayer.state + ' can not stop') + return + } + this.avPlayer.stop() + if (this.onStopCallback) { + this.onStopCallback({}) + } + } + + seek(position) { + if (!this.avPlayer) { + console.error(`[AdvancedAPI] avPlayer is not exist, seek fail`) + return + } + if (![StateType.PREPARED, StateType.PLAYING, StateType.PAUSED, StateType.COMPLETED].includes(this.avPlayer.state)) { + console.error('current state is ' + this.avPlayer.state + ' can not seek') + return + } + if (this.onSeekingCallback) { + this.onSeekingCallback({}) + } + this.avPlayer.seek(position * 1000) + } + + destroy() { + if (!this.avPlayer) { + console.error(`[AdvancedAPI] avPlayer is not exist`) + return + } + this.avPlayer.release() + } + + onCanplay(callback) { + this.onCanplayCallback = callback + } + + offCanplay() { + this.onCanplayCallback = null + } + + onPlay(callback) { + this.onPlayCallback = callback + } + + offPlay() { + this.onPlayCallback = null + } + + onPause(callback) { + this.onPauseCallback = callback + } + + offPause() { + this.onPauseCallback = null + } + + onStop(callback) { + this.onStopCallback = callback + } + + offStop() { + this.onStopCallback = null + } + + onEnded(callback) { + this.onEndedCallback = callback + } + + offEnded() { + this.onEndedCallback = null + } + + onTimeUpdate(callback) { + this.onTimeUpdateCallback = callback + } + + offTimeUpdate() { + this.onTimeUpdateCallback = null + } + + onError(callback) { + this.onErrorCallback = callback + } + + offError() { + this.onErrorCallback = null + } + + onPrev(callback) { + console.info('ios only') + } + + onNext(callback) { + console.info('ios only') + } + + onWaiting(callback) { + this.onWaitingCallback = callback + } + + offWaiting() { + this.onWaitingCallback = null + } + + onSeeking(callback) { + this.onSeekingCallback = callback + } + + offSeeking() { + this.onSeekingCallback = null + } + + onSeeked(callback) { + this.onSeekedCallback = callback + } + + offSeeked() { + this.onSeekedCallback = null + } +} diff --git a/ohos/AdvancedAPI_OHOS/src/advancedApi/module/ASAuthentication/index.js b/ohos/AdvancedAPI_OHOS/src/advancedApi/module/ASAuthentication/index.js new file mode 100644 index 0000000000..4d43d14cb4 --- /dev/null +++ b/ohos/AdvancedAPI_OHOS/src/advancedApi/module/ASAuthentication/index.js @@ -0,0 +1,181 @@ +// eslint-disable-next-line camelcase +import userIAM_userAuth from '@ohos.userIAM.userAuth' +import prompt from '@ohos.prompt' + +const AUTH_RESULT = { + PERMISSION_CHECK_FAIL: 201, /* Permission verification failed. */ + PARAM_ERROR: 401, /* Incorrect parameters. */ + FAIL: 12500001, /* Authentication failed. */ + OPEN_ERROR: 12500002, /* General operation error. */ + USER_CANCEL: 12500003, /* The operation is canceled. */ + TIME_OUT: 12500004, /* The operation is time-out. */ + TYPE_UNSUPPORTED: 12500005, /* The authentication type is not supported. */ + TRUSTED_LEVEL_UNSUPPORTED: 12500006, /* The authentication trust level is not supported. */ + TASK_BUSY: 12500007, /* The authentication task is busy. */ + AUTHENTICATOR_LOCKED: 12500009, /* The authenticator is locked. */ + NOT_ENROLLED: 12500010, /* The type of credential has not been enrolled. */ +} + +function toUint8Arr(str) { + const buffer = [] + for (const i of str) { + const _code = i.charCodeAt(0) + if (_code < 0x80) { + buffer.push(_code) + } else if (_code < 0x800) { + buffer.push(0xc0 + (_code >> 6)) + buffer.push(0x80 + (_code & 0x3f)) + } else if (_code < 0x10000) { + buffer.push(0xe0 + (_code >> 12)) + buffer.push(0x80 + (_code >> 6 & 0x3f)) + buffer.push(0x80 + (_code & 0x3f)) + } + } + return Uint8Array.from(buffer) +} + +export default class ASAuthentication { + start(params) { + return new Promise((resolve, reject) => { + const type = (params && params.requestAuthModes) || '' + // 当前鸿蒙仅支持faceId解锁 + if (type !== 'facial') { + reject({ errCode: 90003, errMsg: 'The authentication type is not supported.' }) + return + } + const challenge = params.challenge + // uni的字符串challenge转换成鸿蒙的数组challenge + const challengeArr = toUint8Arr(challenge) + const authContent = (params && params.authContent) || '' + // 当前仅支持faceId解锁 + const authType = userIAM_userAuth.UserAuthType.FACE + // 认证结果的信任等级 + const authTrustLevel = userIAM_userAuth.AuthTrustLevel.ATL1 + try { + const auth = userIAM_userAuth.getAuthInstance(challengeArr, authType, authTrustLevel) + // 订阅认证结果: userIAM_userAuth.AuthResultInfo + auth.on('result', { + callback: (result) => { + console.debug('[AdvancedAPI] authV9 result ' + result.result) + console.debug('[AdvancedAPI] authV9 token ' + result.token) + console.debug('[AdvancedAPI] authV9 remainAttempts ' + result.remainAttempts) + console.debug('[AdvancedAPI] authV9 lockoutDuration ' + result.lockoutDuration) + if (result.result === AUTH_RESULT.PERMISSION_CHECK_FAIL) { + reject({ errCode: 90002, errMsg: 'Permission verification failed.' }) + } else if (result.result === AUTH_RESULT.PARAM_ERROR) { + reject({ errCode: 90004, errMsg: 'Incorrect parameters.' }) + } else if (result.result === AUTH_RESULT.FAIL) { + reject({ errCode: 90009, errMsg: 'Authentication failed.' }) + } else if (result.result === AUTH_RESULT.OPEN_ERROR) { + reject({ errCode: 90009, errMsg: 'General operation error.' }) + } else if (result.result === AUTH_RESULT.USER_CANCEL) { + reject({ errCode: 90008, errMsg: 'The operation is canceled.' }) + } else if (result.result === AUTH_RESULT.TIME_OUT) { + reject({ errCode: 90007, errMsg: 'The operation is time-out.' }) + } else if (result.result === AUTH_RESULT.TYPE_UNSUPPORTED) { + reject({ errCode: 90003, errMsg: 'The authentication type is not supported.' }) + } else if (result.result === AUTH_RESULT.TRUSTED_LEVEL_UNSUPPORTED) { + reject({ errCode: 90003, errMsg: 'The authentication trust level is not supported.' }) + } else if (result.result === AUTH_RESULT.TASK_BUSY) { + reject({ errCode: 90010, errMsg: 'The authentication task is busy.' }) + } else if (result.result === AUTH_RESULT.AUTHENTICATOR_LOCKED) { + reject({ errCode: 90010, errMsg: 'The authenticator is locked.' }) + } else if (result.result === AUTH_RESULT.NOT_ENROLLED) { + reject({ errCode: 90011, errMsg: 'The type of credential has not been enrolled.' }) + } else { + resolve({ + authMode: 'facial', + resultJSON: '', + resultJSONSignature: '', + errCode: 0, + errMsg: undefined + }) + } + } + }) + auth.on('tip', { + callback: (result) => { + switch (result.tip) { + case userIAM_userAuth.FaceTips.FACE_AUTH_TIP_TOO_BRIGHT: + prompt.showToast({ message: '光线太强,获取的图像太亮。' }) + break + + case userIAM_userAuth.FaceTips.FACE_AUTH_TIP_TOO_DARK: + prompt.showToast({ message: '光线太暗,获取的图像太暗。' }) + break + + case userIAM_userAuth.FaceTips.FACE_AUTH_TIP_TOO_CLOSE: + prompt.showToast({ message: '人脸距离设备过近。' }) + break + + case userIAM_userAuth.FaceTips.FACE_AUTH_TIP_TOO_FAR: + prompt.showToast({ message: '人脸距离设备过远。' }) + break + + case userIAM_userAuth.FaceTips.FACE_AUTH_TIP_TOO_HIGH: + prompt.showToast({ message: '设备太高,仅获取到人脸上部。' }) + break + + case userIAM_userAuth.FaceTips.FACE_AUTH_TIP_TOO_LOW: + prompt.showToast({ message: '设备太低,仅获取到人脸下部。' }) + break + + case userIAM_userAuth.FaceTips.FACE_AUTH_TIP_TOO_RIGHT: + prompt.showToast({ message: '设备太靠右,仅获取到人脸右部。' }) + break + + case userIAM_userAuth.FaceTips.FACE_AUTH_TIP_TOO_LEFT: + prompt.showToast({ message: '设备太靠左,仅获取到人脸左部。' }) + break + + case userIAM_userAuth.FaceTips.FACE_AUTH_TIP_TOO_MUCH_MOTION: + prompt.showToast({ message: '在图像采集过程中,用户人脸移动太快。' }) + break + + case userIAM_userAuth.FaceTips.FACE_AUTH_TIP_POOR_GAZE: + prompt.showToast({ message: '没有正视摄像头。' }) + break + + case userIAM_userAuth.FaceTips.FACE_AUTH_TIP_NOT_DETECTED: + prompt.showToast({ message: '没有检测到人脸信息。' }) + break + + default : + console.debug('[AdvancedAPI] %s', JSON.stringify(result)) + } + } + }) + if (authContent) { + console.debug('[AdvancedAPI] showToast authContent = %s', authContent) + prompt.showToast({ + message: authContent + }) + } + auth.start() + console.debug('[AdvancedAPI] authV9 start success') + } catch (error) { + console.debug('[AdvancedAPI] authV9 start error = %s', error) + reject({ errCode: 90007, errMsg: 'General operation fail.' }) + } + }) + } + + getSupportedType() { + console.debug('[AdvancedAPI] start getSupportedType') + return new Promise((resolve) => { + resolve({ supportMode: ['facial'] }) + }) + } + + isEnrolled(params) { + console.debug('[AdvancedAPI] start isEnrolled') + return new Promise((resolve, reject) => { + const checkAuthMode = (params && params.checkAuthMode) || '' + if (checkAuthMode === 'fingerPrint') { + resolve({ isEnrolled: false, errMsg: '' }) + } else if (checkAuthMode === 'facial') { + resolve({ isEnrolled: false, errMsg: 'The type of credential has not been enrolled.' }) + } + }) + } +} diff --git a/ohos/AdvancedAPI_OHOS/src/advancedApi/module/ASBGAudio/index.js b/ohos/AdvancedAPI_OHOS/src/advancedApi/module/ASBGAudio/index.js new file mode 100644 index 0000000000..f392897b75 --- /dev/null +++ b/ohos/AdvancedAPI_OHOS/src/advancedApi/module/ASBGAudio/index.js @@ -0,0 +1,311 @@ +import avSession from '@ohos.multimedia.avsession' +import wantAgent from '@ohos.app.ability.wantAgent' +import media from '@ohos.multimedia.media' +import backgroundTaskManager from '@ohos.resourceschedule.backgroundTaskManager' +import { isFileUri, getFdFromUriOrSandBoxPath, isSandboxPath } from '../../util/index' +import audio from '@ohos.multimedia.audio' +import { AbilityBase, context } from '../../../base/bridge/abilityBase' + +// 音频播放状态 +const StateType = { + // 音频播放空闲 + IDLE: 'idle', + // 音频正在播放 + PLAYING: 'playing', + // 音频暂停播放 + PAUSED: 'paused', + // 音频停止播放 + STOPPED: 'stopped', + // 错误状态 + ERROR: 'error' +} +function createAVSession(backgroundAudioManager) { + console.debug('[AdvancedAPI] createAVSession begin') + avSession.createAVSession(context, 'player', 'audio').then((data) => { + console.debug('[AdvancedAPI] createAVSession succeed') + backgroundAudioManager.avSession = data + }) +} +function destroyAVSession(backgroundAudioManager) { + console.debug('[AdvancedAPI] destroyAVSession begin') + if (backgroundAudioManager.avSession === null) { + console.debug('[AdvancedAPI] avSession is null') + return + } + backgroundAudioManager.avSession.destroy() +} +function startBackgroundTask() { + AbilityBase.getAbilityInfo().then(abilityInfo => { + const wantAgentInfo = { + wants: [ + { + bundleName: abilityInfo.bundleName, + abilityName: abilityInfo.name + } + ], + operationType: wantAgent.OperationType.START_ABILITY, + requestCode: 0, + wantAgentFlags: [wantAgent.WantAgentFlags.UPDATE_PRESENT_FLAG] + } + // use WantAgent to notify + wantAgent.getWantAgent(wantAgentInfo).then((wantAgentObj) => { + return backgroundTaskManager.startBackgroundRunning(context, backgroundTaskManager.BackgroundMode.AUDIO_PLAYBACK, wantAgentObj) + }).then(() => { + console.debug('[AdvancedAPI] start bg operation succeeded') + }).catch((err) => { + console.error('[AdvancedAPI] start bg operation failed Cause: ' + err) + }) + }) +} +function stopBackgroundTask() { + backgroundTaskManager.stopBackgroundRunning(context).then(() => { + console.debug('[AdvancedAPI] stop operation succeeded') + }).catch((err) => { + console.error('[AdvancedAPI] stop operation fail cause: ' + JSON.stringify(err)) + }) +} +export default class ASBGAudio { + constructor() { + this.backgroundAudioManager = new BackgroundAudioManager() + } +} +class BackgroundAudioManager { + constructor() { + this.bufferedS = 0 + this.avSession = null + this.startTimeS = 0 + this.onWaitingCallback = null + this.titleS = null + this.epnameS = null + this.singerS = null + this.coverImgUrlS = null + this.webUrlS = null + this.protocolS = 'http' + this.onFinishCallback = null + this.tempSrc = '' + this.onCanplayCallback = null + this.onPlayCallback = null + this.onPauseCallback = null + this.onStopCallback = null + this.onTimeUpdateCallback = null + this.onErrorCallback = null + this.init() + } + init() { + this.audioPlayer = media.createAudioPlayer() + this.audioPlayer.on('finish', () => { + destroyAVSession(this) + stopBackgroundTask() + if (this.onFinishCallback) { + this.onFinishCallback({}) + } + }) + this.audioPlayer.on('dataLoad', () => { + if (this.onCanplayCallback) { + this.onCanplayCallback({}) + } + }) + this.audioPlayer.on('bufferingUpdate', (infoType, value) => { + console.info(`[AdvancedAPI] bgAudio bufferingUpdate ${infoType} ${value}`) + if (infoType === 3 && value !== 0) { + this.bufferedS = value + if ((this.audioPlayer.currentTime / 1000) >= (this.audioPlayer.duration * value / 100000) && this.onWaitingCallback) { + this.onWaitingCallback({}) + } + } + }) + this.audioPlayer.on('audioInterrupt', (InterruptEvent) => { + console.info('[AdvancedAPI] audioInterrupt:' + JSON.stringify(InterruptEvent)) + if (InterruptEvent.hintType === audio.InterruptHint.INTERRUPT_HINT_PAUSE) { + this.audioPlayer.pause() + } + if (InterruptEvent.hintType === audio.InterruptHint.INTERRUPT_HINT_RESUME) { + this.audioPlayer.play() + } + }) + + this.audioPlayer.on('play', () => { + if (this.onPlayCallback) { + this.onPlayCallback({}) + } + }) + + this.audioPlayer.on('pause', () => { + if (this.onPauseCallback) { + this.onPauseCallback({}) + } + }) + + this.audioPlayer.on('timeUpdate', res => { + if (this.onTimeUpdateCallback) { + this.onTimeUpdateCallback(res / 1000) + } + }) + + this.audioPlayer.on('error', (err) => { + if (this.onErrorCallback) { + this.onErrorCallback(err) + } + }) + } + get duration() { + return this.audioPlayer.duration / 1000 + } + get currentTime() { + return this.audioPlayer.currentTime / 1000 + } + get paused() { + return this.audioPlayer.state === StateType.PAUSED + } + get src() { + return this.audioPlayer.src + } + set src(value) { + if (typeof (value) !== 'string') { + console.error(`[AdvancedAPI] src: ${value} is invalid`) + return + } + if (!value || !(value.startsWith('http:') || value.startsWith('https:') + || isFileUri(value) || isSandboxPath(value))) { + console.error(`[AdvancedAPI] src: ${value} is invalid`) + return + } + let path + if (value.startsWith('http:') || value.startsWith('https:')) { + path = value + } else if (isFileUri(value) || isSandboxPath(value)) { + try { + const fd = getFdFromUriOrSandBoxPath(value) + path = `fd://${fd}` + } catch (error) { + console.info(`${JSON.stringify(error)}`) + } + } + if (this.audioPlayer.src && path !== this.audioPlayer.src) { + this.audioPlayer.reset() + } + this.audioPlayer.src = path + this.tempSrc = value + this.audioPlayer.play() + if (this.startTimeS) { + this.audioPlayer.seek(this.startTimeS) + } + startBackgroundTask() + createAVSession(this) + } + get startTime() { + return this.startTimeS / 1000 + } + set startTime(time) { + this.startTimeS = time * 1000 + } + get buffered() { + return this.audioPlayer.duration * this.bufferedS / 100000 + } + get title() { + return this.titleS + } + set title(titleName) { + this.titleS = titleName + } + get epname() { + return this.epnameS + } + set epname(epName) { + this.epnameS = epName + } + get singer() { + return this.singerS + } + set singer(singerName) { + this.singerS = singerName + } + get coverImgUrl() { + return this.coverImgUrlS + } + set coverImgUrl(url) { + this.coverImgUrlS = url + } + get webUrl() { + return this.webUrlS + } + set webUrl(url) { + this.webUrlS = url + } + get protocol() { + return this.protocolS + } + set protocol(protocolType) { + this.protocolS = protocolType + } + play() { + const state = this.audioPlayer.state + if (![StateType.PAUSED, StateType.STOPPED, StateType.IDLE].includes(state)) { + return + } + if (this.tempSrc && this.audioPlayer.src === '') { + this.src = this.tempSrc + } + this.audioPlayer.play() + startBackgroundTask() + createAVSession(this) + } + pause() { + const state = this.audioPlayer.state + if (StateType.PLAYING !== state) { + return + } + this.audioPlayer.pause() + } + stop() { + const state = this.audioPlayer.state + if (![StateType.PAUSED, StateType.PLAYING].includes(state)) { + return + } + this.audioPlayer.stop() + if (this.onStopCallback) { + this.onStopCallback({}) + } + this.audioPlayer.release() + this.init() + destroyAVSession(this) + stopBackgroundTask() + } + seek(position) { + const state = this.audioPlayer.state + if (![StateType.PAUSED, StateType.PLAYING].includes(state)) { + return + } + this.audioPlayer.seek(position * 1000) + } + onCanplay(callback) { + this.onCanplayCallback = callback + } + onPlay(callback) { + this.onPlayCallback = callback + } + onPause(callback) { + this.onPauseCallback = callback + } + onStop(callback) { + this.onStopCallback = callback + } + onEnded(callback) { + this.onFinishCallback = callback + } + onTimeUpdate(callback) { + this.onTimeUpdateCallback = callback + } + onError(callback) { + this.onErrorCallback = callback + } + onPrev(callback) { + console.info('ios only') + } + onNext(callback) { + console.info('ios only') + } + onWaiting(callback) { + this.onWaitingCallback = callback + } +} diff --git a/ohos/AdvancedAPI_OHOS/src/advancedApi/module/ASBluetooth/index.js b/ohos/AdvancedAPI_OHOS/src/advancedApi/module/ASBluetooth/index.js new file mode 100644 index 0000000000..6176779c4a --- /dev/null +++ b/ohos/AdvancedAPI_OHOS/src/advancedApi/module/ASBluetooth/index.js @@ -0,0 +1,496 @@ +import { BluetoothBase } from '../../../base/bridge/bluetoothBase' +import { BluetoothBaseModule, BLESTATE } from '../../../base/module/Bluetooth/BluetoothBaseModule' +import { BLHErrorCode } from '../../../base/util/ErrorCode' +import { isString, isNumber } from '../../../base/util/checkDataType' + +export default class ASBluetooth extends BluetoothBaseModule { + constructor() { + super() + this.deviceFoundCallback = undefined + this.adapterStateCallback = undefined + this.BLEConnectionStateCallback = undefined + this.initBluetoothDeviceFound() + this.initBluetoothAdapterStateChange() + this.initBLEConnectionStateChange() + } + /** + * Turn on Bluetooth. + * @param {success} function + * @param {fail} function + * @param {complete} function + */ + openBluetoothAdapter() { + return new Promise(async (resolve, reject) => { + const permission = await BluetoothBase.getPermissions() + if (!permission) { + return reject(['permission fail', ErrorCode.USER_REJECT]) + } + const bluetoothState = BluetoothBase.bluetoothState() === BLESTATE.STATE_ON // 获取当前设备蓝牙状态 + if (bluetoothState) { + this.isInit = true + resolve('ok') // 当前蓝牙为打开状态时走success + } else { + reject([['not available', BLHErrorCode.NOT_AVAILABLE]]) + } + }) + } + + /** + * Turn off Bluetooth + * @param {success} function + * @param {fail} function + * @param {complete} function + */ + closeBluetoothAdapter () { + const bluetoothState = BluetoothBase.bluetoothState() === BLESTATE.STATE_OFF // 获取当前设备蓝牙状态 + return new Promise((resolve, reject) => { + if (bluetoothState) { + reject([['bluetooth is not turned', BLHErrorCode.NOT_AVAILABLE]]) // 当前蓝牙为关闭状态时走fail + } else { + this.isInit = false + BluetoothBase.stopBluetoothDiscovery() + // 适配器扫描状态关闭 + this.state.discovering = false + // 存储成功连接ble设备的deviceId + this.deviceIdBle = '' + + // 蓝牙开启期间扫描到的全部设备 + this.scanResult = [] + + // clent实例 + if (this.gattClient) { + try { + this.gattClient.disconnect() + this.gattClient.close() + this.gattClient = null + } catch (err) {} + } + // 扫描监听模式(true:低功耗,false:蓝牙) + this.isOnBle = { mode: false } + // 低功耗蓝牙连接状态 + this.stateBLE = {} + this.services = [] + this.bleCharacteristic = {} + this.characteristicValue = null + this.devicesFoundListeners = [] + this.adapterStateChangeListeners = [] + this.BLEConnectionStateListeners = [] + this.BLECharacteristicListeners = [] + resolve('ok') + } + }) + } + + /** + * Start searching for nearby Bluetooth peripherals. + * @param {services} Array + * @param {allowDuplicatesKey} boolean + * @param {interval} number + * @param {powerLevel} string + * @param {success} function + * @param {fail} function + * @param {complete} function + */ + startBluetoothDevicesDiscovery(params) { + if (this.isInit) { + return this.startDevicesDiscovery(params) + } else { + return new Promise((resolve, reject) => { + console.warn('[AdvancedAPI] bluetooth is no init') + reject([['not init', BLHErrorCode.NOT_INIT]]) + }) + } + } + + /** + * Stop searching for nearby Bluetooth peripherals. + * @param {success} function + * @param {fail} function + * @param {complete} function + */ + stopBluetoothDevicesDiscovery(params) { + if (this.isInit) { + return this.stopDevicesDiscovery(params) + } else { + return new Promise((resolve, reject) => { + console.warn('[AdvancedAPI] bluetooth is no init') + reject([['not init', BLHErrorCode.NOT_INIT]]) + }) + } + } + + initBluetoothDeviceFound() { + this.deviceFoundCallback = device => { + this.onFoundEvent(device) + // 遍历所有监听者,发送消息 + for (const listener of this.devicesFoundListeners) { + // 执行设置的上报间隔(默认无间隔) + setTimeout(() => { + listener([this.scanResult]) + }, this.interval) + } + } + try { + // 开启蓝牙监听 + BluetoothBase.on(this.deviceFoundCallback) + + // 开启低功耗监听 + BluetoothBase.onBLE(this.deviceFoundCallback) + } catch (errMessage) { + console.error(`[AdvancedAPI] openHarmony ondevicefound fail ${errMessage}`) + } + } + + /** + * Listen to the event that a new device is found. + * @param {cb} function + * @param {scanResult} object + */ + onBluetoothDeviceFound(cb) { + this.devicesFoundListeners.push(cb) + } + + offBluetoothDeviceFound(cb) { + if (cb === undefined) { + this.devicesFoundListeners.splice(0) + return + } + if (typeof cb !== 'function') { + console.error('[AdvancedAPI] offBluetoothAdapterStateChange, param is invalid:' + typeof cb) + return + } + const index = this.devicesFoundListeners.indexOf(cb) + if (index > -1) { + this.devicesFoundListeners.splice(index, 1) + } + } + + initBluetoothAdapterStateChange() { + this.adapterStateCallback = (data) => { + const stateValue = this.state.available + if (data === 2) { + this.state.available = true + } else if (data === 0) { + this.state.available = false + } + if (stateValue !== this.state.available) { + // 遍历所有监听者,发送消息 + for (const listener of this.adapterStateChangeListeners) { + listener(stateValue) + } + } + } + + try { + BluetoothBase.onStateChange(data => { + this.adapterStateCallback(data) + }) + } catch (err) { + console.error('[AdvancedAPI] onBluetoothAdapterStateChange errCode:' + err.code + ',errMessage:' + err.message) + } + } + + /** + * Listening for Bluetooth adapter status change events. + * @param {cbFunc} function + * @param {available} boolean + * @param {discovering} boolean + */ + onBluetoothAdapterStateChange(cbFunc) { + this.adapterStateChangeListeners.push(cbFunc) + } + + offBluetoothAdapterStateChange(cb) { + if (cb === undefined) { + this.devicesFoundListeners.splice(0) + return + } + if (typeof cb !== 'function') { + console.error('[AdvancedAPI] offBluetoothAdapterStateChange, param is invalid:') + return + } + const index = this.adapterStateChangeListeners.indexOf(cb) + if (index > -1) { + this.adapterStateChangeListeners.splice(index, 1) + } + } + + /** + * Obtains the connected device based on the UUID. + * @param {services} Array + * @param {success} function + * @param {fail} function + * @param {complete} function + */ + getConnectedBluetoothDevices(params) { + if (this.isInit) { + return this.getConnectedDevices(params) + } else { + return new Promise((resolve, reject) => { + console.warn('[AdvancedAPI] bluetooth is no init') + reject([['not init', BLHErrorCode.NOT_INIT]]) + }) + } + } + + /** + * Obtains all discovered Bluetooth devices during the validity period of the Bluetooth module. + * Including devices that are already connected to the local machine. + * @param {success} function + * @param {fail} function + * @param {complete} function + * @return {devices} Array + */ + getBluetoothDevices() { + if (this.isInit) { + return this.getDevices() + } else { + return new Promise((resolve, reject) => { + console.warn('[AdvancedAPI] bluetooth is no init') + reject([['not init', BLHErrorCode.NOT_INIT]]) + }) + } + } + + /** + * Gets the status of the local Bluetooth adapter. + * @param {discovering} boolean + * @param {available} boolean + */ + getBluetoothAdapterState() { + if (this.isInit) { + return this.getAdapterState() + } else { + return new Promise((resolve, reject) => { + console.warn('[AdvancedAPI] bluetooth is no init') + reject([['not init', BLHErrorCode.NOT_INIT]]) + }) + } + } + + /** + * Sets the Bluetooth MTU.The value range of MTU is 22–512. + * @param {deviceId} string + * @param {mtu} number + * @param {success} function + * @param {fail} function + * @param {complete} function + */ + asSetBLEMTU(params) { + return new Promise((resolve, reject) => { + if (!params || !params.deviceId || !params.mtu) { + console.error('[AdvancedAPI] setBLEMTU fail, params error') + reject([['param error', BLHErrorCode.SYSTEM_ERROR]]) + return + } + if (!isString(params.deviceId) || !isNumber(params.mtu)) { + console.error('[AdvancedAPI] setBLEMTU fail, params error') + reject([['param error', BLHErrorCode.SYSTEM_ERROR]]) + return + } + try { + console.debug('[AdvancedAPI] asSetBLEMTU deviceId:' + params.deviceId + ' this.deviceIdBLE = ' + this.deviceIdBle) + // 获取实例 + let gattClient + if (this.gattClient && params.deviceId.toLowerCase() === this.deviceIdBle.toLowerCase()) { + console.debug('[AdvancedAPI] asSetBLEMTU deviceId:' + params.deviceId) + gattClient = this.gattClient + } else { + gattClient = BluetoothBase.createGattClientDevice(params.deviceId) + gattClient.connect() + this.gattClient = gattClient + this.deviceIdBle = params.deviceId + } + this.gattClient.setBLEMtuSize(params.mtu) + resolve('ok') + } catch (err) { + console.error('[AdvancedAPI] setBLEMtuSize fail, errCode:' + err.code + ',errMessage:' + err.message) + reject([[err.message, BLHErrorCode.SYSTEM_ERROR]]) + } + }) + } + + /** + * Writes binary data to the Bluetooth Low Energy device characteristic value. + * Note: The function can be successfully called only when the feature value of the device supports write. + * @param {deviceId} string + * @param {serviceId} string + * @param {characteristicId} string + * @param {value} ArrayBuffer + * @param {writeType} string + * @param {success} function + * @param {fail} function + * @param {complete} function + */ + asWriteBLECharacteristicValue(params) { + return this.writeBLECharacteristicValue(params) + } + + /** + * Reads the binary data value of the Bluetooth Low Energy device's characteristic value + * Note: The function can be successfully invoked only when the feature value of the device supports read. + * @param {deviceId} string + * @param {serviceId} string + * @param {characteristicId} string + * @param {success} function + * @param {fail} function + * @param {complete} function + */ + asReadBLECharacteristicValue(params) { + return this.readBLECharacteristicValue(params) + } + + initBLEConnectionStateChange() { + this.BLEConnectionStateCallback = (stateChange) => { + // 遍历所有的监听者 + this.BLEConnectionStateListeners.forEach(callback => { + callback(stateChange) + }) + } + this.stateBLE = new Proxy({}, { + get: (target, key) => { + return target[key] + }, + set: (target, key, value) => { + target[key] = value + const state = { + deviceId: key, + connected: value + } + console.debug('AdvancedAPI bleConnectionStateChange') + this.BLEConnectionStateCallback(state) + return true + } + }) + } + + /** + * Listen for Bluetooth low energy connection status change events. + * including the developer's active connection or disconnection, device loss, and abnormal disconnection. + * @param {success} function + * @param {fail} function + * @param {complete} function + */ + asOnBLEConnectionStateChange(cb) { + this.BLEConnectionStateListeners.push(cb) + } + + asOffBLEConnectionStateChange(cb) { + if (cb === undefined) { + this.BLEConnectionStateListeners.splice(0) + return + } + if (typeof cb !== 'function') { + console.error('[AdvancedAPI] offBLEConnectionStateChange, param is invalid:') + return + } + const index = this.BLEConnectionStateListeners.indexOf(cb) + if (index > -1) { + this.BLEConnectionStateListeners.splice(index, 1) + } + } + + /** + * Turn on Bluetooth. + * @param {success} function + * @param {fail} function + * @param {complete} function + */ + asOnBLECharacteristicValueChange(cb) { + this.BLECharacteristicListeners.push(cb) + } + + asOffBLECharacteristicValueChange(cb) { + if (cb === undefined) { + this.BLECharacteristicListeners.splice(0) + return + } + if (typeof cb !== 'function') { + console.error('[AdvancedAPI] offBLECharacteristicValueChange, param is invalid:') + return + } + const index = this.BLECharacteristicListeners.indexOf(cb) + if (index > -1) { + this.BLECharacteristicListeners.splice(index, 1) + } + } + + /** + * Turn on Bluetooth. + * @param {success} function + * @param {fail} function + * @param {complete} function + */ + asNotifyBLECharacteristicValueChange(params) { + console.debug('[AdvancedAPI] params = ' + JSON.stringify(params)) + return this.notifyBLECharacteristicValueChange(params) + } + + /** + * Turn on Bluetooth. + * @param {success} function + * @param {fail} function + * @param {complete} function + */ + asGetBLEDeviceServices(params) { + return this.getBLEDeviceServices(params) + } + + /** + * Obtains the signal strength of a Bluetooth device. + * @param {deviceId} string + * @param {success} function + * @param {fail} function + * @param {complete} function + */ + asGetBLEDeviceRSSI(params) { + return new Promise((resolve, reject) => { + if (!params || !params.deviceId || typeof params.deviceId !== 'string') { + reject([['invalidParams', BLHErrorCode.SYSTEM_ERROR]]) + return + } + this.getBLEDeviceRSSI(params.deviceId).then((result) => { + resolve({ rssi: result }) + }).catch(err => { + reject([[err, BLHErrorCode.SYSTEM_ERROR]]) + }) + }) + } + + /** + * Obtains all feature values in a service of a Bluetooth device. + * @param {deviceId} string + * @param {serviceId} string + * @param {success} function + * @param {fail} function + * @param {complete} function + */ + asGetBLEDeviceCharacteristics(params) { + return this.getBLEDeviceCharacteristics(params) + } + + /** + * Connect the Bluetooth Low Energy device. + * @param {deviceId} string + * @param {success} function + * @param {fail} function + * @param {complete} function + */ + asCreateBLEConnection(params) { + if (params) { + console.info('[AdvancedAPI] asCreateBLEConnection params = ' + JSON.stringify(params)) + } + return this.createBLEConnection(params) + } + + /** + * Disconnect the Bluetooth Low Energy device. + * @param {deviceId} string + * @param {success} function + * @param {fail} function + * @param {complete} function + */ + asCloseBLEConnection(params) { + return this.closeBLEConnection(params) + } +} diff --git a/ohos/AdvancedAPI_OHOS/src/advancedApi/module/ASBrightness/index.js b/ohos/AdvancedAPI_OHOS/src/advancedApi/module/ASBrightness/index.js new file mode 100644 index 0000000000..248c35f64b --- /dev/null +++ b/ohos/AdvancedAPI_OHOS/src/advancedApi/module/ASBrightness/index.js @@ -0,0 +1,25 @@ +import { ErrorCode } from '../../../base/util/ErrorCode' +import { BrightnessBaseModule } from '../../../base/module/Brightness/BrightnessBaseModule' + +export default class ASBrightness extends BrightnessBaseModule { + setScreenBrightness(params) { + console.info('[AdvancedAPI] params = ' + JSON.stringify(params)) + if (params && params.value !== undefined && (typeof params.value === 'number')) { + const value = params.value + if (value <= 1 && value >= 0) { + return this.setValue({ value: Math.round(params.value * 255) }) + } + } + return new Promise((resolve, reject) => { + reject(['param is invalid.', ErrorCode.PARAMETER_ERROR]) + }) + } + + getScreenBrightness() { + return this.getValue() + } + + asSetKeepScreenOn(params) { + return this.setKeepScreenOn(params) + } +} diff --git a/ohos/AdvancedAPI_OHOS/src/advancedApi/module/ASBuffer/index.js b/ohos/AdvancedAPI_OHOS/src/advancedApi/module/ASBuffer/index.js new file mode 100644 index 0000000000..dfa265bd98 --- /dev/null +++ b/ohos/AdvancedAPI_OHOS/src/advancedApi/module/ASBuffer/index.js @@ -0,0 +1,20 @@ +import buffer from '@ohos.buffer' + +export default class ASBuffer { + /** + * 将 ArrayBuffer 对象转成 Base64 字符串 + * @param {arrayBuffer} arrayBuffer - 要转化成 ArrayBuffer 对象的 Base64 字符串 + * @return {string} - base64编码的字符串 + */ + arrayBufferToBase64 (arrayBuffer) { + if (!arrayBuffer || arrayBuffer.byteLength === undefined) { + return new Error('[AdvancedAPI] [arrayBufferToBase64] param type is not arrayBuffer') + } + if (!(arrayBuffer instanceof Uint8Array)) { + arrayBuffer = new Uint8Array(arrayBuffer) + } + const buf = buffer.allocUninitializedFromPool(arrayBuffer.byteLength) + const b = buf.fill(arrayBuffer) + return b.toString('base64') + } +} diff --git a/ohos/AdvancedAPI_OHOS/src/advancedApi/module/ASCapture/index.js b/ohos/AdvancedAPI_OHOS/src/advancedApi/module/ASCapture/index.js new file mode 100644 index 0000000000..e4f1b5020d --- /dev/null +++ b/ohos/AdvancedAPI_OHOS/src/advancedApi/module/ASCapture/index.js @@ -0,0 +1,86 @@ +/** + * Copyright (c) Huawei Technologies Co., Ltd. 2023-2023. All rights reserved. + * Description: advanced capture screen event api + * Create: 04/10/2023 + * Notes: + */ +import window from '@ohos.window' + +// AS API class +export default class ASCapture { + /** + * constructor function, init callback map + */ + constructor() { + this.captureCallback = null + } + + /** + * subscribe user capture screen event + * @callback params path {String}: capture file storage path (ohos not support) + */ + onUserCaptureScreen(callback) { + if (!callback) { + console.error('[AdvancedAPI] params illegal, empty callback') + return + } + try { + window.getLastWindow(globalThis.abilityContext).then((data) => { + this.windowClass = data + + function screenshotCallback() { + callback('ohos not support path') + } + + if (this.captureCallback) { + this.windowClass.off('screenshot') + this.captureCallback = null + } + this.captureCallback = callback + + console.info('[AdvancedAPI] Succeeded in obtaining the top window. Listen to screenshot event.') + try { + this.windowClass.on('screenshot', screenshotCallback) + } catch (exception) { + console.error('[AdvancedAPI] Failed to register callback. Cause: ' + JSON.stringify(exception)) + } + }).catch((err) => { + console.error('[AdvancedAPI] Failed to obtain the top window. Cause: ' + JSON.stringify(err)) + }) + } catch (exception) { + console.error('[AdvancedAPI] Failed to obtain the top window. Cause: ' + JSON.stringify(exception)) + } + } + + /** + * unsubscribe user capture screen event + * remove all if callback is null, otherwise remove the specialized callback + */ + offUserCaptureScreen(callback) { + try { + window.getLastWindow(globalThis.abilityContext).then((data) => { + this.windowClass = data + console.info('[AdvancedAPI] Succeeded in obtaining the top window. Unsubscribe screenshot event.') + try { + if (callback) { + if (this.captureCallback && this.captureCallback === callback) { + this.windowClass.off('screenshot') + this.captureCallback = null + } else { + console.info('[AdvancedAPI] Invalid callback.') + } + } else { + this.windowClass.off('screenshot') + this.captureCallback = null + } + } catch (exception) { + console.error('[AdvancedAPI] Failed to unregister callback. Cause: ' + JSON.stringify(exception)) + } + }).catch((err) => { + console.error('[AdvancedAPI] Failed to obtain the top window. Cause: ' + JSON.stringify(err)) + }) + } catch (exception) { + console.error('[AdvancedAPI] Failed to obtain the top window. Cause: ' + JSON.stringify(exception)) + } + } +} diff --git a/ohos/AdvancedAPI_OHOS/src/advancedApi/module/ASCompass/index.js b/ohos/AdvancedAPI_OHOS/src/advancedApi/module/ASCompass/index.js new file mode 100644 index 0000000000..4698d14b94 --- /dev/null +++ b/ohos/AdvancedAPI_OHOS/src/advancedApi/module/ASCompass/index.js @@ -0,0 +1,85 @@ +/** + * Copyright (c) Huawei Technologies Co., Ltd. 2023-2023. All rights reserved. + * Description: Advanced API Compass + * Author: 00430169 + * Create: 7/4/2023 + * Notes: N/A + */ + +import { OhosSensorBase } from '../../../base/bridge/sensorBase' +import { ErrorCode } from '../../../base/util/ErrorCode' + +export default class ASCompass { + constructor () { + this.callBackCompassSet = new Set() + } + + onCompassChange (callback) { + return new Promise(async (resolve, reject) => { + if (typeof callback !== 'function') { + reject('param is invalid.', ErrorCode.PARAMETER_ERROR) + return + } + if (this.callBackCompassSet.has(callback)) { + reject('param is invalid.', ErrorCode.PARAMETER_ERROR) + } else { + this.callBackCompassSet.add(callback) + OhosSensorBase.ohosSubscribeCompass({ callback: (data) => { + const accuracy = 3 // 高精度 + const res = { + direction: data.alpha, + accuracy: data.alpha ? accuracy : 0 + } + for (const cb of this.callBackCompassSet.keys()) { + cb(res) + } + } }) + resolve() + } + }) + } + + offCompassChange (callback) { + return new Promise(async (resolve, reject) => { + if (typeof callback !== 'function') { + // compass off change默认不传参数时不取消所有监听 + reject('param is invalid.', ErrorCode.PARAMETER_ERROR) + return + } + if (!this.callBackCompassSet.has(callback)) { + reject('param is invalid.', ErrorCode.PARAMETER_ERROR) + } else { + this.callBackCompassSet.delete(callback) + if (this.callBackCompassSet.size === 0) { + OhosSensorBase.ohosUnsubscribeCompass() + } + resolve('success') + } + }) + } + + startCompass (object) { + return new Promise(async (resolve, reject) => { + OhosSensorBase.ohosSubscribeCompass({ + callback: (data) => { + const accuracy = 3 // 高精度 + const res = { + direction: data.alpha, + accuracy: data.alpha ? accuracy : 0 + } + for (const cb of this.callBackCompassSet.keys()) { + cb(res) + } + } + }) + resolve('success') + }) + } + + stopCompass () { + return new Promise(async (resolve, reject) => { + OhosSensorBase.ohosUnsubscribeCompass() + resolve('success') + }) + } +} diff --git a/ohos/AdvancedAPI_OHOS/src/advancedApi/module/ASContact/index.js b/ohos/AdvancedAPI_OHOS/src/advancedApi/module/ASContact/index.js new file mode 100644 index 0000000000..12cdf6e704 --- /dev/null +++ b/ohos/AdvancedAPI_OHOS/src/advancedApi/module/ASContact/index.js @@ -0,0 +1,188 @@ +/** + * Copyright (c) Huawei Technologies Co., Ltd. 2022-2022. All rights reserved. + * Description: default description + * Author: weisufang + * Create: 04/12/2023 + * 需要权限: ohos.permission.WRITE_CONTACTS + */ + +import contact from '@ohos.contact' +import { context } from '../../../base/bridge/abilityBase' +import abilityAccessCtrl from '@ohos.abilityAccessCtrl' +import { ErrorCode } from '../../../base/util/ErrorCode' + +export default class ASContact { + /** + * 调用后,用户可以选择将该表单以“新增联系人”或“添加到已有联系人”的方式(APP端目前没有选择步骤,将直接写入) + * 写入手机系统通讯录,完成手机通讯录联系人和联系方式的增加。 + * @param {string} photoFilePath 头像本地文件路径 + * @param {string} nickName 昵称 + * @param {string} lastName 姓氏 + * @param {string} middleName 中间名 + * @param {string} firstName 名字 + * @param {string} remark 备注 + * @param {string} mobilePhoneNumber 手机号 + * @param {string} weChatNumber 微信号 + * @param {string} addressCountry 联系地址国家 + * @param {string} addressState 联系地址省份 + * @param {string} addressCity 联系地址城市 + * @param {string} addressStreet 联系地址街道 + * @param {string} addressPostalCode 联系地址邮政编码 + * @param {string} organization 公司 + * @param {string} title 职位 + * @param {string} workFaxNumber 工作传真 + * @param {string} workPhoneNumber 工作电话 + * @param {string} hostNumber 公司电话 + * @param {string} email 电子邮件 + * @param {string} url 网站 + * @param {string} workAddressCountry 工作地址国家 + * @param {string} workAddressState 工作地址省份 + * @param {string} workAddressCity 工作地址城市 + * @param {string} workAddressStreet 工作地址街道 + * @param {string} workAddressPostalCode 工作地址邮政编码 + * @param {string} homeFaxNumber 住宅传真 + * @param {string} homePhoneNumber 住宅电话 + * @param {string} homeAddressCountry 住宅地址国家 + * @param {string} homeAddressState 住宅地址省份 + * @param {string} homeAddressCity 住宅地址城市 + * @param {string} homeAddressStreet 住宅地址街道 + * @param {string} homeAddressPostalCode 住宅地址邮政编码 + * @param {function} success - 接口调用成功的回调函数 + * @param {function} fail - 接口调用失败的回调函数 + * @param {function} complete - 接口调用结束的回调函数(调用成功、失败都会执行) + */ + addPhoneContact (params) { + return new Promise(async (resolve, reject) => { + try { + const atManager = abilityAccessCtrl.createAtManager() + const { authResults, dialogShownResults} = await atManager.requestPermissionsFromUser(context, ['ohos.permission.WRITE_CONTACTS']) + if (authResults[0] === 0) { + console.debug('[AdvancedAPI] request WRITE_CONTACTS permission success') + } else { + // 权限拒绝 + reject(['request permission fail', ErrorCode.USER_REJECT, authResults[0], dialogShownResults[0]]) + return + } + } catch (err) { + reject(['request permission fail', ErrorCode.USER_REJECT]) + return + } + const { + photoFilePath, + nickName = '', + lastName = '', + middleName = '', + firstName = '', + remark, + mobilePhoneNumber, + weChatNumber, + addressCountry = '', + addressState = '', + addressCity = '', + addressStreet = '', + addressPostalCode, + organization, + url, + workPhoneNumber, + workFaxNumber, + hostNumber, + email, + title, + workAddressCountry = '', + workAddressState = '', + workAddressCity = '', + workAddressStreet = '', + workAddressPostalCode, + homeFaxNumber, + homePhoneNumber, + homeAddressCountry = '', + homeAddressState = '', + homeAddressCity = '', + homeAddressStreet = '', + homeAddressPostalCode + } = params + + if (!weChatNumber) { + console.error('[AdvancedAPI] weChatNumber do not support.') + } + + if (!firstName) { + console.error('[AdvancedAPI] firstName is required.') + reject(['fail Missing required parameter `firstName`', ErrorCode.PARAMETER_ERROR]) + return + } + + const contactInfo = { + name: { + familyName: lastName, + middleName: middleName, + givenName: firstName, + fullName: lastName + middleName + firstName + }, + nickName: { + nickName + }, + emails: [{ + email: email, + displayName: '邮箱' + }], + phoneNumbers: [{ + phoneNumber: homePhoneNumber, + labelId: contact.PhoneNumber.NUM_HOME + }, { + phoneNumber: mobilePhoneNumber, + labelId: contact.PhoneNumber.NUM_MOBILE + }, { + phoneNumber: homeFaxNumber, + labelId: contact.PhoneNumber.NUM_FAX_HOME + }, { + phoneNumber: workFaxNumber, + labelId: contact.PhoneNumber.NUM_FAX_WORK + }, { + phoneNumber: workPhoneNumber, + labelId: contact.PhoneNumber.NUM_WORK + }, { + phoneNumber: hostNumber, + labelId: contact.PhoneNumber.NUM_COMPANY_MAIN + }], + portrait: { uri: photoFilePath }, + postalAddresses: [{ + city: homeAddressCity, + country: homeAddressCountry, + postcode: homeAddressPostalCode, + street: homeAddressStreet, + postalAddress: homeAddressCountry + homeAddressState + homeAddressCity + homeAddressStreet, + labelId: contact.PostalAddress.ADDR_HOME + }, { + city: workAddressCity, + country: workAddressCountry, + postcode: workAddressPostalCode, + street: workAddressStreet, + postalAddress: workAddressCountry + workAddressState + workAddressCity + workAddressStreet, + labelId: contact.PostalAddress.ADDR_WORK + }, { + city: addressCity, + country: addressCountry, + postcode: addressPostalCode, + street: addressStreet, + postalAddress: addressCountry + addressState + addressCity + addressStreet, + labelId: contact.PostalAddress.CUSTOM_LABEL + }], + websites: [{ website: url }], + note: { noteContent: remark }, + organization: { + name: organization, + title + } + } + + contact.addContact(contactInfo).then((contactId) => { + console.debug(`[AdvancedAPI] addContact callback: success contactId = ${contactId}`) + resolve() + }).catch((err) => { + console.debug(`[AdvancedAPI] addContact callback: err->${JSON.stringify(err)}`) + reject([err.data, err.code]) + }) + }) + } +} diff --git a/ohos/AdvancedAPI_OHOS/src/advancedApi/module/ASDevice/index.js b/ohos/AdvancedAPI_OHOS/src/advancedApi/module/ASDevice/index.js new file mode 100644 index 0000000000..7d7c6bd214 --- /dev/null +++ b/ohos/AdvancedAPI_OHOS/src/advancedApi/module/ASDevice/index.js @@ -0,0 +1,351 @@ +import { DeivceBase } from '../../../base/bridge/deviceBase' +import { DisplayBase } from '../../../base/bridge/displayBase' +import I18n from '@ohos.i18n' +import abilityAccessCtrl from '@ohos.abilityAccessCtrl' +import { context } from '../../../base/bridge/abilityBase' +import bluetooth from '@ohos.bluetooth' +import geoLocationManager from '@ohos.geoLocationManager' +import wifiManager from '@ohos.wifiManager' +import window from '@ohos.window' + +export default class ASDevice { + getSystemInfoSync () { + const { + brand: deviceBrand, + productModel: deviceModel, + osFullName, + deviceType, + udid: deviceId, + sdkApiVersion: ohosAPILevel + } = DeivceBase.getDeviceInfo() + const romName = osFullName.split('-')[0] + const osName = romName + const romVersion = osFullName.split('-')[1] + const osVersion = romVersion + + const osLanguage = I18n.System.getSystemLanguage() + const displayInfo = DisplayBase.ohosGetDisplay() + const { rotation, densityPixels: devicePixelRatio } = displayInfo + let { width: screenWidth, height: screenHeight } = displayInfo + screenWidth = Math.round(screenWidth / devicePixelRatio) + screenHeight = Math.round(screenHeight / devicePixelRatio) + const deviceOrientation = (rotation === 1 || rotation === 3) ? 'landscape' : 'portrait' + + const { + signatureInfo, + versionName: appVersion, + versionCode: appVersionCode, + appInfo + } = globalThis.bundleInfoForSelf + const appName = context.resourceManager.getStringSync(appInfo.labelId) + const appId = signatureInfo.appId + + const { + language: appLanguage + } = context.config + + let { + width: windowWidth, + height: windowHeight, + top: windowTop + } = globalThis.lastWindow.getWindowProperties()?.windowRect + const { + isFullScreen, isLayoutFullScreen + } = globalThis.lastWindow.getWindowProperties() + const systemCutout = globalThis.lastWindow.getWindowAvoidArea(window.AvoidAreaType.TYPE_SYSTEM) + const statusBarHeight = Math.round((systemCutout?.topRect?.height || 0) / devicePixelRatio) + const windowBottom = (isFullScreen || isLayoutFullScreen) ? Math.round(windowHeight / devicePixelRatio) : + Math.round((windowHeight + statusBarHeight) / devicePixelRatio) + windowTop = Math.round(windowTop / devicePixelRatio) + windowWidth = Math.round(windowWidth / devicePixelRatio) + windowHeight = Math.round(windowHeight / devicePixelRatio) + + const brand = deviceBrand + const model = deviceModel + const pixelRatio = devicePixelRatio + const system = osFullName + const language = osLanguage + const platform = osName + const version = osVersion + const result = { + deviceType, + deviceBrand, + brand, + deviceModel, + platform, + model, + deviceOrientation, + devicePixelRatio, + pixelRatio, + system, + osName, + osVersion, + version, + osLanguage, + language, + ohosAPILevel, + romName, + romVersion, + appId, + appName, + appVersion, + appVersionCode, + appLanguage, + screenWidth, + screenHeight, + windowWidth, + windowHeight, + windowTop, + windowBottom, + statusBarHeight + } + if (deviceId) { + result.deviceId = deviceId + } + return result + } + + getDeviceInfo () { + console.debug('[AdvancedAPI] start ASDevice getDeviceInfo') + const { + brand, + productModel: deviceModel, + osFullName: system, + deviceType, + osFullName, + udid: deviceId + } = DeivceBase.getDeviceInfo() + const deviceBrand = brand + const model = deviceModel + const platform = osFullName.split('-')[0] + const { + densityPixels: devicePixelRatio, + rotation + } = DisplayBase.ohosGetDisplay() + const deviceOrientation = (rotation === 1 || rotation === 3) ? 'landscape' : 'portrait' + const result = { + platform, + deviceBrand, + deviceModel, + deviceType, + deviceOrientation, + devicePixelRatio, + system, + brand, + model + } + if (deviceId) { + result.deviceId = deviceId + } + return result + } + + getWindowInfo () { + console.debug('[AdvancedAPI] start ASDevice getWindowInfo') + const display = DisplayBase.ohosGetDisplay() + + const { densityPixels: pixelRatio } = display + let { + width: screenWidth, + height: screenHeight + } = display + + let { + width: windowWidth, + height: windowHeight, + top: windowTop + } = globalThis.lastWindow.getWindowProperties()?.windowRect + const { + isFullScreen, + isLayoutFullScreen + } = globalThis.lastWindow.getWindowProperties() + const systemCutout = globalThis.lastWindow.getWindowAvoidArea(window.AvoidAreaType.TYPE_SYSTEM) + const statusBarHeight = Math.round((systemCutout?.topRect?.height || 0) / pixelRatio) + const windowBottom = (isFullScreen || isLayoutFullScreen) ? Math.round(windowHeight / pixelRatio) : + Math.round((windowHeight + statusBarHeight) / pixelRatio) + windowTop = Math.round(windowTop / pixelRatio) + windowWidth = Math.round(windowWidth / pixelRatio) + windowHeight = Math.round(windowHeight / pixelRatio) + screenWidth = Math.round(screenWidth / pixelRatio) + screenHeight = Math.round(screenHeight / pixelRatio) + return { + pixelRatio, + screenWidth, + screenHeight, + windowWidth, + windowHeight, + windowTop, + windowBottom, + statusBarHeight + } + } + getAppBaseInfo() { + console.debug('[AdvancedAPI] start ASDevice getAppBaseInfo') + const { + signatureInfo, + versionName: appVersion, + versionCode: appVersionCode, + appInfo + } = globalThis.bundleInfoForSelf + const enableDebug = appInfo.debug + const appName = context.resourceManager.getStringSync(appInfo.labelId) + const appId = signatureInfo.appId + const { + language: appLanguage + } = context.config + // eslint-disable-next-line no-undef + Environment.envProp('colorMode', -1) + const colorMode = AppStorage.get('colorMode') + const theme = colorMode === 0 ? 'light' : (colorMode === 1 ? 'dark' : 'auto') + return { + appId, + appName, + appVersion, + appVersionCode, + appLanguage, + enableDebug, + theme + } + } + getAppAuthorizeSetting() { + console.debug('[AdvancedAPI] start ASDevice getAppAuthorizeSetting') + const permissionsList = { + album: 'ohos.permission.WRITE_IMAGEVIDEO', + bluetooth: 'ohos.permission.USE_BLUETOOTH', + camera: 'ohos.permission.CAMERA', + location: 'ohos.permission.LOCATION', + locationAccuracy: 'ohos.permission.APPROXIMATELY_LOCATION', + microphone: 'ohos.permission.MICROPHONE', + notification: 'ohos.permission.NOTIFICATION_CONTROLLER', + phoneCalendar: 'ohos.permission.READ_CALENDAR' + } + + const atManager = abilityAccessCtrl.createAtManager() + const info = globalThis.bundleInfoForSelf + const tokenID = info.appInfo.accessTokenId + const grantStatus = (flag) => { + if (flag === -1) { + return 'denied' + } else if (flag === 0) { + return 'authorized' + } + return 'config error' + } + let albumAuthorized = 'not determined' + try { + albumAuthorized = atManager.checkAccessTokenSync(tokenID, permissionsList.album) + albumAuthorized = grantStatus(albumAuthorized) + } catch (e) { + console.debug('[AdvancedAPI] ASDevice getAppAuthorizeSetting checkAccessToken album fail') + } + let bluetoothAuthorized = 'not determined' + try { + bluetoothAuthorized = atManager.checkAccessTokenSync(tokenID, permissionsList.bluetooth) + bluetoothAuthorized = grantStatus(bluetoothAuthorized) + } catch (e) { + console.debug('[AdvancedAPI] ASDevice getAppAuthorizeSetting checkAccessToken bluetooth fail') + } + let cameraAuthorized = 'not determined' + try { + cameraAuthorized = atManager.checkAccessTokenSync(tokenID, permissionsList.camera) + cameraAuthorized = grantStatus(cameraAuthorized) + } catch (e) { + console.debug('[AdvancedAPI] ASDevice getAppAuthorizeSetting checkAccessToken camera fail') + } + let locationAuthorized = 'not determined' + try { + locationAuthorized = atManager.checkAccessTokenSync(tokenID, permissionsList.location) + locationAuthorized = grantStatus(locationAuthorized) + } catch (e) { + console.debug('[AdvancedAPI] ASDevice getAppAuthorizeSetting checkAccessToken location fail') + } + let locationAccuracy = 'not determined' + try { + locationAccuracy = (atManager.checkAccessTokenSync(tokenID, permissionsList.locationAccuracy)) === 0 ? 'full' : 'reduced' + } catch (e) { + console.debug('[AdvancedAPI] ASDevice getAppAuthorizeSetting checkAccessToken locationAccuracy fail') + } + let microphoneAuthorized = 'not determined' + try { + microphoneAuthorized = atManager.checkAccessTokenSync(tokenID, permissionsList.microphone) + microphoneAuthorized = grantStatus(microphoneAuthorized) + } catch (e) { + console.debug('[AdvancedAPI] ASDevice getAppAuthorizeSetting checkAccessToken microphone fail') + } + let notificationAuthorized = 'not determined' + try { + notificationAuthorized = atManager.checkAccessTokenSync(tokenID, permissionsList.notification) + notificationAuthorized = grantStatus(notificationAuthorized) + } catch (e) { + console.debug('[AdvancedAPI] ASDevice getAppAuthorizeSetting checkAccessToken notification fail') + } + let phoneCalendarAuthorized = 'not determined' + try { + phoneCalendarAuthorized = atManager.checkAccessTokenSync(tokenID, permissionsList.phoneCalendar) + phoneCalendarAuthorized = grantStatus(phoneCalendarAuthorized) + } catch (e) { + console.debug('[AdvancedAPI] ASDevice getAppAuthorizeSetting checkAccessToken phoneCalendar fail') + } + + const result = { + albumAuthorized, + bluetoothAuthorized, + cameraAuthorized, + locationAuthorized, + locationAccuracy, + microphoneAuthorized, + notificationAuthorized, + phoneCalendarAuthorized + } + return result + } + getSystemSetting() { + let bluetoothEnabled + let locationEnabled + let wifiEnabled + let bluetoothError + let locationError + try { + bluetoothEnabled = bluetooth.getState() + bluetoothEnabled = !!(bluetoothEnabled === 2 || bluetoothEnabled === 5) + } catch (err) { + console.error('errCode:' + err.code + ',errMessage:' + err.message) + bluetoothError = err.message + } + try { + locationEnabled = geoLocationManager.isLocationEnabled() + } catch (err) { + console.error('errCode:' + err.code + ',errMessage:' + err.message) + locationError = err.message + } + try { + wifiEnabled = wifiManager.isWifiActive() + } catch (err) { + console.error('errCode:' + err.code + ',errMessage:' + err.message) + } + const { + rotation + } = DisplayBase.ohosGetDisplay() + const deviceOrientation = (rotation === 1 || rotation === 3) ? 'landscape' : 'portrait' + return { + bluetoothEnabled, + bluetoothError, + locationEnabled, + locationError, + wifiEnabled, + deviceOrientation + } + } + + openAppAuthorizeSetting() { + const want = { + bundleName: 'com.huawei.hmos.settings', + abilityName: 'com.huawei.hmos.settings.MainAbility', + uri: 'application_info_entry', + parameters: { + pushParams: context.applicationInfo.name // 打开指定应用的详情页面 + } + } + return context.startAbilityForResult(want) + } +} diff --git a/ohos/AdvancedAPI_OHOS/src/advancedApi/module/ASFile/FileCallback.js b/ohos/AdvancedAPI_OHOS/src/advancedApi/module/ASFile/FileCallback.js new file mode 100644 index 0000000000..631be5fec1 --- /dev/null +++ b/ohos/AdvancedAPI_OHOS/src/advancedApi/module/ASFile/FileCallback.js @@ -0,0 +1,49 @@ +import { checkDataType } from '../../../base/util/checkDataType' + +export default class FileCallback { + constructor({ success, fail, complete }) { + if (checkDataType(success, false, 'function')) { + this.successFn = success + } + if (checkDataType(fail, false, 'function')) { + this.failFn = fail + } + if (checkDataType(complete, false, 'function')) { + this.completeFn = complete + } + } + + success (...args) { + if (this.successFn) { + try { + this.successFn(...args) + } catch (err) { + console.error(err) + } + } + if (this.completeFn) { + try { + this.completeFn(...args) + } catch (err) { + console.error(err) + } + } + } + + fail (...args) { + if (this.failFn) { + try { + this.failFn(...args) + } catch (err) { + console.error(err) + } + } + if (this.completeFn) { + try { + this.completeFn(...args) + } catch (err) { + console.error(err) + } + } + } +} diff --git a/ohos/AdvancedAPI_OHOS/src/advancedApi/module/ASFile/FileError.js b/ohos/AdvancedAPI_OHOS/src/advancedApi/module/ASFile/FileError.js new file mode 100644 index 0000000000..a656319f84 --- /dev/null +++ b/ohos/AdvancedAPI_OHOS/src/advancedApi/module/ASFile/FileError.js @@ -0,0 +1,41 @@ +const FILE_ERROR = { + OPERATION_NOT_PERMITTED: 1300001, // 操作不被允许(例如,filePath 预期传入一个文件而实际传入一个目录) + NO_SUCH_FILE_OR_DIRECTORY: 1300002, // 文件/目录不存在,或者目标文件路径的上层目录不存在 + INPUT_ERROR: 1300005, // 输入流不可用 + OUTPUT_ERROR: 1300005, // 输出流不可用 + BAD_FILE_DESCRIPTOR: 1300009, // 无效的文件描述符 + PERMISSION_DENIED: 1300013, // 权限错误,文件是只读或只写 + PATH_PERMISSION_DENIED: 1300014, // 传入的路径没有权限 + NOT_DIRECTORY: 1300020, // dirPath 指定路径不是目录,常见于指定的写入路径的上级路径为一个文件的情况 + IS_DIRECTORY: 1300021, // 指定路径是一个目录 + INVALID_ARGUMENT: 1300022, // 无效参数,可以检查length或offset是否越界 + FILE_NAME_TOO_LONG: 1300036, // 文件名过长 + DIRECTORY_NOT_EMPTY: 1300066, // directory not empty + SYSTEM_ERROR: 1300201, // 系统接口调用失败 + STORAGE_MAXIMUN_SIZE_EXCEEDED: 1300202, // 存储空间不足,或文件大小超出上限(上限100M) + BASE64_ENCODE_ERROR: 1300203, // 字符编码转换失败(例如 base64 格式错误) + SDCARD_NOT_MOUNTED: 1300300, // android sdcard 挂载失败 + UNABLE_OPEN_AS_FILETYPE: 1300301, // 无法以fileType打开文件 + CANNOT_ACCESS_FILE_PATH: 1301000, // 目标路径无访问权限(usr目录) + DATA_TO_WRITE_EMPTY: 1301002, // 写入数据为空 + ILLEGAL_OPERATION_ON_DIRECTORY: 1301003, // 不可对目录进行此操作(例如,指定的 filePath 是一个已经存在的目录) + ILLEGAL_OPERATION_ON_PACKAGE_DIRECTORY: 1301004, // 不可对代码包目录进行此操作 + FILE_ALREADY_EXISTS: 1301005, // 已有同名文件或目录 + LENGTH_VALUE_OUTOF_RANGE: 1301006, // 传入的 length 不合法 + OFFSET_VALUE_OUTOF_RANGE: 1301007, // 传入的 offset 不合法 + POSITION_VALUE_OUTOF_RANGE: 1301009, // position值越界 + STORE_DERECTORY_EMPTY: 1301100, // store目录为空 + UNZIP_OPEN_FEIL_FAIL: 1301102, // 压缩文件打开失败 + UNZIP_ENTRY_FAIL: 1301103, // 解压单个文件失败 + UNZIP_FAIL: 1301104, // 解压失败 + BROTLI_DECOMPRESS_FAIL: 1301111, // brotli解压失败(例如,指定的 compressionAlgorithm 与文件实际压缩格式不符) + TEMPFILEPATH_FILE_NOT_EXIST: 1301112, // 指定的 tempFilePath 找不到文件 + FAIL_PERMISSION_DENIED: 1302001, // 指定的 fd 路径没有读权限/没有写权限 + EXCCED_MAX_CONCURRENT_FD_LIMIT: 1302002, // fd数量已达上限 + INVALID_FLAG: 1302003, // 无效的flag + PERMISSION_DENIED_WHEN_OPEN_USING_FLAG: 1302004, // 无法使用flag标志打开文件 + ARRAY_BUFFER_DOES_NOT_EXISTl: 1302005, // 未传入arrayBuffer + ARRAY_BUFFER_IS_READONLY: 1302100 // arrayBuffer只读 +} + +export default FILE_ERROR diff --git a/ohos/AdvancedAPI_OHOS/src/advancedApi/module/ASFile/FileSystemManager.js b/ohos/AdvancedAPI_OHOS/src/advancedApi/module/ASFile/FileSystemManager.js new file mode 100644 index 0000000000..6f8c101b76 --- /dev/null +++ b/ohos/AdvancedAPI_OHOS/src/advancedApi/module/ASFile/FileSystemManager.js @@ -0,0 +1,998 @@ +import fs from '@ohos.file.fs' +import buffer from '@ohos.buffer' +import { context } from '../../../base/bridge/abilityBase' +import { checkDataType } from '../../../base/util/checkDataType' +import FileCallback from './FileCallback' +import { + getOpenMode, + modeReflect, + getFileTypeMode, + mkdirRecursive, + checkFd, + checkFdSync, + checkEncoding, + checkPath, + checkPathSync, + checkPathExistence, + checkPathExistenceSync, + obtainFileName, + obtainUpperPath, +} from './util' +import { isSandboxPath, switchInternalToHapSandBox } from '../../util' + +const ERROR = { + PARAMETER_ERROR: 1001 +} + +const DEFAULT_ENCODING = 'utf-8' +const DEFAULT_POSITION = 0 +const DEFAULT_LENGTH = 0 +const DEFAULT_FLAG = 'r' +const DEFAULT_OFFSET = 0 +const FLAG = [ + 'a', // 打开文件用于追加。 如果文件不存在,则创建该文件 + 'ax', // 类似于 'a',但如果路径存在,则失败 + 'a+', // 打开文件用于读取和追加。 如果文件不存在,则创建该文件 + 'ax+', // 类似于 'a+',但如果路径存在,则失败 + 'as', // 打开文件用于追加(在同步模式中)。 如果文件不存在,则创建该文件 + 'as+', // 打开文件用于读取和追加(在同步模式中)。 如果文件不存在,则创建该文件 + 'r', // 打开文件用于读取。 如果文件不存在,则会发生异常 + 'r+', // 打开文件用于读取和写入。 如果文件不存在,则会发生异常 + 'w', // 打开文件用于写入。 如果文件不存在则创建文件,如果文件存在则截断文件 + 'wx', // 类似于 'w',但如果路径存在,则失败 + 'w+', // 打开文件用于读取和写入。 如果文件不存在则创建文件,如果文件存在则截断文件 + 'wx+', // 类似于 'w+',但如果路径存在,则失败 +] + +export default class FileSystemManager { + constructor() { + this.pathDir = context.filesDir // 沙箱路径 + } + + access ({ path, success, fail, complete }) { + const cb = new FileCallback({ success, fail, complete }) + const fileUri = isSandboxPath(path) ? switchInternalToHapSandBox(path) : path + if (!checkDataType(fileUri, true, 'string')) { + cb.fail({ + errMsg: 'access:fail parameter error: parameter.path should be String', + errno: ERROR.PARAMETER_ERROR // 对齐微信错误码 + }) + return + } + fs.access(fileUri).then(res => { + if (res) { + console.debug('[AdvancedAPI] file access exist') + cb.success({ errMsg: 'access:ok' }) + } else { + cb.fail({ errMsg: 'access:fail no such file or directory' }) + } + }, (err) => { + console.debug('[AdvancedAPI] access failed with error message: %s, code = %d', err.message, err.code) + }) + } + + accessSync (path) { + if (!checkDataType(path, true, 'string')) { + throw new Error('accessSync:fail path must be a string') + } + const res = fs.accessSync(path) + if (!res) { + throw new Error('accessSync:fail no such file or directory') + } + } + + // 当数据是string类型时有效,表示数据的编码方式,默认 ‘utf-8’。当前仅支持 ‘utf-8’ + appendFile ({ filePath, data, encoding = DEFAULT_ENCODING, success, fail, complete }) { + const cb = new FileCallback({ success, fail, complete }) + if (!checkDataType(filePath, true, 'string')) { + cb.fail({ + errMsg: 'access:fail parameter error: parameter.filePath should be String', + errno: ERROR.PARAMETER_ERROR + }) + return + } + if (!checkDataType(data, true, ['string', 'arraybuffer'])) { + cb.fail({ + errMsg: 'access:fail parameter error: parameter.data should be String/ArrayBuffer', + errno: ERROR.PARAMETER_ERROR + }) + return + } + + const res = fs.accessSync(filePath) + if (!res) { + cb.fail({ errMsg: `appendFile:fail no such file or directory, open "${filePath}"` }) + return + } + + const file = fs.openSync(filePath, fs.OpenMode.READ_WRITE | fs.OpenMode.APPEND) + fs.write(file.fd, data).then(writeLen => { + cb.success({ errMsg: 'appendFile:ok' }) + fs.closeSync(file) + }).catch((err) => { + console.error('[AdvancedAPI] appendFile failed with error message: ' + err.message + ', error code: ' + err.code) + cb.fail({ errMsg: `appendFile:fail ${err.message}` }) + }) + } + + // 当数据是string类型时有效,表示数据的编码方式,默认 ‘utf-8’。当前仅支持 ‘utf-8’ + appendFileSync (filePath, data, encoding = DEFAULT_ENCODING) { + if (!checkDataType(filePath, true, 'string')) { + throw new Error('access:fail parameter error: parameter.filePath should be String') + } + if (!checkDataType(data, true, ['string', 'arraybuffer'])) { + throw new Error('access:fail parameter error: parameter.data should be String/ArrayBuffer') + } + + const res = fs.accessSync(filePath) + if (!res) { + throw new Error(`appendFile:fail no such file or directory, open "${filePath}"`) + } + + const file = fs.openSync(filePath, fs.OpenMode.READ_WRITE | fs.OpenMode.APPEND) + fs.writeSync(file.fd, data) + } + + // 打开文件,返回文件描述符 + open ({ filePath, flag = DEFAULT_FLAG, success, fail, complete }) { + const cb = new FileCallback({ success, fail, complete }) + if (!checkDataType(filePath, true, 'string')) { + cb.fail({ + errMsg: 'open:fail parameter error: parameter.filePath should be String', + errno: ERROR.PARAMETER_ERROR + }) + return + } + if (!FLAG.includes(flag)) { + flag = DEFAULT_FLAG + } + + if (Object.keys(modeReflect).includes(flag)) { + const res = fs.accessSync(filePath) + if (!res) { + console.debug('[AdvancedAPI] access fail') + flag = modeReflect[flag] + } else { + cb.fail({ errMsg: 'open:fail EXIST: file already exists' }) + return + } + } + + fs.open(filePath, getOpenMode(flag), (err, file) => { + if (err) { + console.error('[AdvancedAPI] open failed with error message: ' + err.message + ', error code: ' + err.code) + cb.fail({ + errMsg: `open:fail ${err.message}`, + errno: ERROR.NO_SUCH_FILE_OR_DIRECTORY + }) + } else { + cb.success({ fd: file.fd.toString(), errMsg: 'open:ok' }) + } + }) + } + + openSync ({ filePath, flag }) { + if (!checkDataType(filePath, true, 'string')) { + throw new Error('openSync:fail parameter error: parameter.filePath should be String') + } + if (!FLAG.includes(flag)) { + flag = DEFAULT_FLAG + } + + if (Object.keys(modeReflect).includes(flag)) { + const res = fs.accessSync(filePath) + if (!res) { + console.debug('[AdvancedAPI] access fail') + flag = modeReflect[flag] + } else { + throw new Error('openSync:fail EXIST: file already exists') + } + } + + const file = fs.openSync(filePath, getOpenMode(flag)) + return file.fd.toString() + } + + close ({ fd, success, fail, complete }) { + const cb = new FileCallback({ success, fail, complete }) + if (fd === '' || !checkDataType(fd, true, 'string')) { + cb.fail({ + errMsg: 'close:fail invalid fd', + errno: ERROR.PARAMETER_ERROR + }) + return + } + fd = Number(fd) + if (isNaN(fd)) { + cb.fail({ errMsg: `close:fail bad file descriptor` }) + return + } + fs.close(fd, err => { + if (err) { + cb.fail({ errMsg: `close:fail bad file descriptor` }) + } else { + cb.success({ errMsg: 'close:ok' }) + } + }) + } + + closeSync ({ fd }) { + if (fd === '' || !checkDataType(fd, true, 'string')) { + throw new Error('closeSync:fail invalid fd') + } + fd = Number(fd) + if (isNaN(fd)) { + throw new Error('closeSync:fail invalid fd') + } + fs.closeSync(fd) + } + + // 差异: srcPath与destPath相同时,微信提示成功,但鸿蒙抛出异常,提示Error: File exists + copyFile ({ srcPath, destPath, success, fail, complete }) { + const cb = new FileCallback({ success, fail, complete }) + const checkResOfSrcPath = checkPathExistence('copyFile', 'srcPath', srcPath) + if (!checkResOfSrcPath.isValid) { + cb.fail(checkResOfSrcPath.checkMsg) + return + } + + const checkResOfDestPath = checkPath('copyFile', 'destPath', destPath) + if (!checkResOfDestPath.isValid) { + cb.fail(checkResOfDestPath.checkMsg) + return + } + + // 判断srcPath是否为一个目录 + if (fs.statSync(srcPath).isDirectory()) { + cb.fail({ errMsg: `copyFile: fail illegal operation on a directory, open: ${srcPath}` }) + return + } + + // 判断destPath路径是否存在 + if (!fs.accessSync(destPath)) { + const getUpperPath = obtainUpperPath(destPath) + + // copyFile不支持创建目录 upperPath不存在直接报错 + if (!fs.accessSync(getUpperPath.upperPath)) { + cb.fail({ errMsg: `copyFile: fail no such file or directory, open: ${destPath}` }) + return + } + } else { + const destPathStat = fs.statSync(destPath) + // 路径存在且为目录,则拼接srcPath的文件名作为destPath + if (destPathStat.isDirectory()) { + destPath = destPath + obtainFileName(srcPath).fileName + } else { + // 路径存在且为文件,源路径必须与目标路径相同 + if (destPathStat.isFile() && (srcPath !== destPath)) { + cb.fail({ errMsg: 'copyFile: fail copyFile failed' }) + return + } + } + } + + fs.copyFile(srcPath, destPath) + .then(() => { + cb.success({ errMsg: 'copyFile: ok' }) + }) + .catch((err) => { + cb.fail({ errMsg: `copyFile: failed with error message: ${err.message}, error code: ${err.code}` }) + }) + } + + // 差异: srcPath与destPath相同时,微信提示成功,但鸿蒙抛出异常,提示Error: File exists + copyFileSync (srcPath, destPath) { + const checkResSrc = checkPathExistenceSync('copyFileSync', 'srcPath', srcPath) + if (!checkResSrc.isValid) { + throw new Error(checkResSrc.errMsg) + } + + const checkResDest = checkPathSync('copyFileSync', 'destPath', destPath) + if (!checkResDest.isValid) { + throw new Error(checkResDest.errMsg) + } + + if (fs.statSync(srcPath).isDirectory()) { + throw new Error(`copyFileSync: fail illegal operation on a directory: ${srcPath}`) + } + + if (!fs.accessSync(destPath)) { + const getUpperPath = obtainUpperPath(destPath) + if (!fs.accessSync(getUpperPath.upperPath)) { + throw new Error(`copyFileSync: fail no such file or directory: ${destPath}`) + } + } else { + // 判断存在的路径是目录还是文件 + const destPathStat = fs.statSync(destPath) + // 判断存在的路径是目录还是文件 + if (destPathStat.isDirectory()) { + const index = destPath.lastIndexOf('/') + let namePath = destPath.substring(index) + + // 处理' ../test.txt/ '的情况 + if (destPath.endsWith('/')) { + namePath = destPath.substring(destPath.lastIndexOf('/', destPath.length - 2) + 1, destPath.length - 1) + } + + destPath = destPath + namePath + } else { + // 判断destPath是否等于srcPath, 若不等,则报错 + if (destPathStat.isFile() && (srcPath !== destPath)) { + throw new Error('copyFileSync: fail copyFile failed') + } + } + } + + try { + fs.copyFileSync(srcPath, destPath) + } catch (err) { + throw new Error(`copyFileSync: ${err.message}`) + } + } + + fstat ({ fd, success, fail, complete }) { + const cb = new FileCallback({ success, fail, complete }) + const res = checkFd('fstat', fd) + if (!res.isValid) { + cb.fail(res.checkMsg) + return + } else { + fd = res.fd + } + + fs.stat(fd, (err, stat) => { + if (err) { + cb.fail({ errMsg: `fstat: failed with error message: ${err.message}, error code: ${err.code}` }) + } else { + const combinationMode = getFileTypeMode(stat) | stat.mode + cb.success({ + stat: { + mode: combinationMode, + size: stat.size, + lastAccessedTime: stat.atime, + lastModifiedTime: stat.mtime, + isDirectory: () => { return stat.isDirectory() }, + isFile: () => { return stat.isFile() }, + }, + errMsg: 'fstat: ok' + }) + } + }) + } + + fstatSync ({ fd }) { + const res = checkFdSync('fstatSync', fd) + if (!res.isValid) { + throw new Error(res.errMsg) + } else { + fd = res.fd + } + + try { + const stat = fs.statSync(fd) + const combinationMode = getFileTypeMode(stat) | stat.mode + return { + stat: { + mode: combinationMode, + size: stat.size, + lastAccessedTime: stat.atime, + lastModifiedTime: stat.mtime, + isDirectory: () => { return stat.isDirectory() }, + isFile: () => { return stat.isFile() } + } + } + } catch (err) { + throw new Error(`fstatSync: ${err.message}`) + } + } + + ftruncate ({ fd, length, success, fail, complete }) { + const cb = new FileCallback({ success, fail, complete }) + const res = checkFd('ftruncate', fd) + if (!res.isValid) { + cb.fail(res.checkMsg) + return + } else { + fd = res.fd + } + + if (!checkDataType(length, true, 'number') || length < 0) { + length = DEFAULT_LENGTH // 非number类型 设为默认值DEFAULT_LENGTH ,DEFAULT_LENGTH=0 + } + + fs.truncate(fd, length).then(() => { + cb.success({ errMsg: 'ftruncate: ok' }) + }).catch((err) => { + cb.fail({ errMsg: `ftruncate: failed with error message: ${err.message}, error code: ${err.code}` }) + }) + } + + ftruncateSync ({ fd, length }) { + const res = checkFdSync('ftruncateSync', fd) + if (!res.isValid) { + throw new Error(res.errMsg) + } else { + fd = res.fd + } + + if (!checkDataType(length, true, 'number') || length < 0) { + length = DEFAULT_LENGTH // 非number类型 设为默认值DEFAULT_LENGTH ,DEFAULT_LENGTH=0 + } + + try { + fs.truncateSync(fd, length) + } catch (err) { + throw new Error(`ftruncateSync: ${err.message}`) + } + } + + mkdir ({ dirPath, recursive, success, fail, complete }) { + const cb = new FileCallback({ success, fail, complete }) + // 将非boolean类型的入参转换为boolean类型 + if (!checkDataType(recursive, false, 'boolean')) { + recursive = Boolean(recursive) + } + + const checkRes = checkPath('mkdir', 'dirPath', dirPath) + if (!checkRes.isValid) { + cb.fail(checkRes.checkMsg) + return + } + + // 检查目录是否已经存在 + if (fs.accessSync(dirPath)) { + cb.fail({ errMsg: `mkdir: dirPath already exists: ${dirPath}` }) + return + } + + // 是否递归创建 + if (recursive) { + mkdirRecursive('', dirPath.split('/')) + cb.success({ errMsg: 'mkdir: ok' }) + } else { + const getSubPath = obtainUpperPath(dirPath) + if (fs.accessSync(getSubPath.upperPath)) { + fs.mkdir(dirPath) + .then(() => { + cb.success({ errMsg: 'mkdir: ok' }) + }) + .catch((err) => { + cb.fail({ + errMsg: `mkdir: failed with error message: ${err.message}, error code: ${err.code}` + }) + }) + } else { + cb.fail({ errMsg: 'mkdir: failed' }) + } + } + } + + mkdirSync (dirPath, recursive) { + // 将非boolean类型的入参转换为boolean类型 + if (!checkDataType(recursive, false, 'boolean')) { + recursive = Boolean(recursive) + } + + const res = checkPathSync('mkdirSync', 'dirPath', dirPath) + if (!res.isValid) { + throw new Error(res.errMsg) + } + + // 检查目录是否已经存在 + if (fs.accessSync(dirPath)) { + throw new Error(`mkdirSync: dirPath already exists: ${dirPath}`) + } + + // recursive为false且上级目录不存在 + if (!recursive && !fs.accessSync(obtainUpperPath(dirPath).upperPath)) { + throw new Error(`mkdirSync: fail, recursive is false and upper path does not exist`) + } + + if (recursive) { + try { + mkdirRecursive('', dirPath.split('/')) + } catch (err) { + throw new Error(`mkdirSync: ${err.message}`) + } + } else { + try { + fs.mkdirSync(dirPath) + } catch (err) { + throw new Error(`mkdirSync: ${err.message}`) + } + } + } + + // 仅负责读取文件,需要开发者手动打开文件,调完read接口后,手动关闭文件 + read ({ fd, arrayBuffer, offset = DEFAULT_OFFSET, length, position, success, fail, complete }) { + const cb = new FileCallback({ success, fail, complete }) + + if (!checkDataType(fd, true, 'string') || fd === '' || isNaN(Number(fd))) { + cb.fail({ errMsg: 'read: fail invalid fd' }) + return + } else { + fd = Number(fd) + } + + if (!checkDataType(arrayBuffer, true, 'arraybuffer')) { + cb.fail({ errMsg: `read: fail invalid arrayBuffer: ${arrayBuffer}` }) + return + } + + // offset、length、position为负数时,微信不报错也读不出内容,但鸿蒙接口会crash + if (!checkDataType(offset, false, 'number') || offset < 0) { + offset = Number(offset) // 转换非number类型的数据,转换结果:true = 1, false = 0, '12' = 12, null = 0 + if (isNaN(offset) || offset < 0) { + offset = DEFAULT_OFFSET // 其他类型如object、undefined, 设为默认值 + } + } + + if (!checkDataType(length, false, 'number') || length < 0) { + length = Number(length) + if (isNaN(length) || length < 0) { + length = DEFAULT_LENGTH + } + } + + const allowedSize = arrayBuffer.byteLength - offset // ArrayBuffer中允许读取的最大容量 + if (allowedSize < length) { + cb.fail({ errMsg: `read: fail RangeError [ERR_OUT_OF_RANGE]: The value length is out of range. It must be <= ${allowedSize}. Received ${length}` }) + return + } + + if (!checkDataType(position, false, 'number') || position < 0) { + position = DEFAULT_POSITION // 非number类型,设为默认值 + } + + /* + * 参数说明: + * 【微信中】 + * offset: number类型,缓冲区中的写入偏移量,默认0 + * length: number类型,要从文件中读取的字节数,默认0 + * position: number类型,文件读取的起始位置,如不传或传 null,则会从当前文件指针的位置读取。 + * 如果 position 是正整数,则文件指针位置会保持不变并从 position 读取文件 + * 【鸿蒙中】 + * offset: number类型,期望读取文件的位置。默认从当前位置开始读。 + * length: number类型,期望读取数据的长度。默认缓冲区长度。 + */ + const offsetArrayBuffer = offset // 缓冲区要求写入的偏移量 + const newBuffer = arrayBuffer.slice(offsetArrayBuffer) // 临时申请一块新的空间 + fs.read(fd, newBuffer, { offset: position, length }) + .then((readLen) => { + const viewNewBuffer = new Uint8Array(newBuffer) + const viewArrayBuffer = new Uint8Array(arrayBuffer) + viewArrayBuffer.set(viewNewBuffer, offsetArrayBuffer) + console.debug('[AdvancedAPI] the content of arrayBuffer: %s', String.fromCharCode.apply(null, new Uint8Array(newBuffer.slice(0, readLen)))) + cb.success({ + bytesRead: readLen, + arrayBuffer: arrayBuffer, + errMsg: 'read: ok' + }) + }) + .catch((err) => { + cb.fail({ errMsg: `read: failed with error message: ${err.message},error code: ${err.code}` }) + }) + } + + // 仅负责读取文件,需要开发者手动打开文件,调完read接口后,手动关闭文件 + readSync ({ fd, arrayBuffer, offset, length, position }) { + if (!checkDataType(fd, true, 'string') || fd === '' || isNaN(Number(fd))) { + throw new Error('readSync:fail invalid fd') + } else { + fd = Number(fd) + } + + if (!checkDataType(arrayBuffer, true, 'arraybuffer')) { + throw new Error('readSync: fail invalid arrayBuffer') + } + + if (!checkDataType(offset, false, 'number') || offset < 0) { + offset = Number(offset) // 转换非number类型的数据,转换结果:true = 1, false = 0, '12' = 12, null = 0 + if (isNaN(offset) || offset < 0) { + offset = DEFAULT_OFFSET // 其他类型如object、undefined, 设为默认值 + } + } + + if (!checkDataType(length, false, 'number') || length < 0) { + length = Number(length) + if (isNaN(length) || length < 0) { + length = DEFAULT_LENGTH + } + } + + const allowedSize = arrayBuffer.byteLength - offset // ArrayBuffer中允许读取的最大容量 + if (allowedSize < length) { + throw new Error(`readSync: fail RangeError [ERR_OUT_OF_RANGE]: The value length is out of range. It must be <= ${allowedSize}. Received ${length}`) + } + + if (!checkDataType(position, false, 'number') || position < 0) { + position = DEFAULT_POSITION // 非number类型,设为默认值 + } + + /* + * 参数说明: + * @微信中 + * offset: number类型,缓冲区中的写入偏移量,默认0 + * length: number类型,要从文件中读取的字节数,默认0 + * position: number类型,文件读取的起始位置,如不传或传 null,则会从当前文件指针的位置读取。 + * 如果 position 是正整数,则文件指针位置会保持不变并从 position 读取文件 + * @鸿蒙中 + * offset: number类型,期望读取文件的位置。默认从当前位置开始读。 + * length: number类型,期望读取数据的长度。默认缓冲区长度。 + */ + try { + const offsetArrayBuffer = offset // 缓冲区要求写入的偏移量 + const newBuffer = arrayBuffer.slice(offsetArrayBuffer) // 临时申请一块新的空间 + const len = fs.readSync(fd, newBuffer, { offset: position, length }) + const viewNewBuffer = new Uint8Array(newBuffer) // 创建视图用于操纵数据,在入参arrayBuffer的偏移量为offsetArrayBuffer的位置写入数据 + const viewArrayBuffer = new Uint8Array(arrayBuffer) + viewArrayBuffer.set(viewNewBuffer, offsetArrayBuffer) + console.debug('[AdvancedAPI] the content of arrayBuffer: %s', String.fromCharCode.apply(null, new Uint8Array(arrayBuffer.slice(0, len)))) + + return { bytesRead: len, arrayBuffer: arrayBuffer } + } catch (err) { + throw new Error(`readSync: ${err.message}`) + } + } + + /** + * 功能:readdir读取目录的文件列表 使用鸿蒙的listFile实现(列出文件夹下所有文件名) + * 差异:微信支持访问空串,读取到的结果是根目录的文件列表;鸿蒙listFile判定空串是合法的,但读不到根目录的内容,返回的内容为空 + * 由于鸿蒙的一些接口如accessSync 、 statSync 认为空串是非法的,所以该接口也将空串按照非法值处理,不返回空内容 + */ + readdir ({ dirPath, success, fail, complete }) { + const cb = new FileCallback({ success, fail, complete }) + const checkRes = checkPathExistence('readdir', 'dirPath', dirPath) + if (!checkRes.isValid) { + cb.fail(checkRes.checkMsg) + return + } + + const stat = fs.statSync(dirPath) + if (stat.isFile()) { + cb.fail({ errMsg: `readdir: fail, dirPath not a directory: ${dirPath}` }) + return + } + + fs.listFile(dirPath) + .then((files) => { + cb.success({ + files, + errMsg: 'readdir: ok' + }) + }) + .catch((err) => { + cb.fail({ errMsg: `readdir: failed with error message: ${err.message}, error code: ${err.code}` }) + }) + } + + readdirSync (dirPath) { + const res = checkPathExistence('readdirSync', 'dirPath', dirPath) + if (!res.isValid) { + throw new Error(res.errMsg) + } + + if (fs.statSync(dirPath).isFile()) { + throw new Error('readdirSync: fail not a directory: ${dirPath}') + } + + try { + const files = fs.listFileSync(dirPath) + return { files } + } catch (err) { + throw new Error(`readdirSync: ${err.message}`) + } + } + + readFile ({ filePath, encoding, position = DEFAULT_POSITION, length, success, fail, complete }) { + filePath = isSandboxPath(filePath) ? switchInternalToHapSandBox(filePath) : filePath + const cb = new FileCallback({ success, fail, complete }) + const checkRes = checkPathExistence('readFile', 'filePath', filePath) + if (!checkRes.isValid) { + cb.fail(checkRes.checkMsg) + return + } + + const stat = fs.statSync(filePath) + if (stat.isDirectory()) { + cb.fail({ errMsg: `readFile:fail not absolute path: ${filePath}` }) + return + } + + const res = checkEncoding('readFile', encoding) + if (!res.isValid) { + cb.fail({ errMsg: res.checkMsg }) + return + } + + const lengthOfFile = stat.size + length = (length === undefined || length === null) ? lengthOfFile : length + + if (!checkDataType(position, false, 'number')) { + cb.fail({ errMsg: `readFile:fail invalid position: ${position}` }) + return + } + + if (!checkDataType(length, false, 'number')) { + cb.fail({ errMsg: `readFile:fail invalid length: ${length}` }) + return + } + + if (position < 0 || position > lengthOfFile) { + cb.fail({ errMsg: 'readFile:fail the value of "position" is out of range' }) + return + } + + if (length < 0 || length + position > lengthOfFile) { + cb.fail({ errMsg: 'readFile:fail the value of "length" is out of range' }) + return + } + + const file = fs.openSync(filePath, fs.OpenMode.READ_ONLY) + const buf = new ArrayBuffer(length) + fs.read(file.fd, buf, { position, length }) + .then(() => { + const data = encoding ? buffer.from(buf).toString(encoding) : buf + cb.success({ + data, + errMsg: 'readFile:ok' + }) + }) + .catch((err) => { + cb.fail({ errMsg: `readFile:fail error message: ${err.message}, error code: ${err.code}` }) + }) + .finally(() => { + fs.closeSync(file) + }) + } + + readFileSync (filePath, encoding, position = DEFAULT_POSITION, length) { + filePath = isSandboxPath(filePath) ? switchInternalToHapSandBox(filePath) : filePath + const res1 = checkPathExistenceSync('readFileSync', 'filePath', filePath) + if (!res1.isValid) { + throw new Error(res1.errMsg) + } + // 判断filePath是文件还是目录 + const stat = fs.statSync(filePath) + if (stat.isDirectory()) { + throw new Error(`readFileSync:fail illegal operation on a directory, open: ${filePath}`) + } + + const res2 = checkEncoding('readFile', encoding) + if (!res2.isValid) { + throw new Error(res2.checkMsg) + } + + const lengthOfFile = stat.size + length = (length === undefined || length === null) ? lengthOfFile : length + + if (!checkDataType(position, false, 'number')) { + throw new Error(`readFileSync:fail invalid position: ${position}`) + } + + if (!checkDataType(length, false, 'number')) { + throw new Error(`readFileSync:fail invalid length: ${length}`) + } + + if (position < 0 || position > lengthOfFile) { + throw new Error('readFileSync:fail the value of "position" is out of range') + } + + if (length < 0 || length + position > lengthOfFile) { + throw new Error('readFileSync:fail the value of "length" is out of range') + } + + try { + const file = fs.openSync(filePath, fs.OpenMode.READ_ONLY) + const buf = new ArrayBuffer(length) + fs.readSync(file.fd, buf, { position, length }) + fs.closeSync(file) + const data = encoding ? buffer.from(buf).toString(encoding) : buf + return data + } catch (err) { + throw new Error(`readFileSync:fail ${err.message}`) + } + } + + rename ({ oldPath, newPath, success, fail, complete }) { + const cb = new FileCallback({ success, fail, complete }) + const checkRes1 = checkPathExistence('rename', 'oldPath', oldPath) + if (!checkRes1.isValid) { + cb.fail(checkRes1.checkMsg) + return + } + + const checkRes2 = checkPath('rename', 'newPath', newPath) + if (!checkRes2.isValid) { + cb.fail(checkRes2.checkMsg) + return + } + + const ifAccessNewPath = fs.accessSync(newPath) + if (!ifAccessNewPath) { + const getUpperPath = obtainUpperPath(newPath) + if (!fs.accessSync(getUpperPath.upperPath)) { + cb.fail({ errMsg: `rename: fail no such file or directory: ${newPath}` }) + return + } + } + + if (ifAccessNewPath && (oldPath !== newPath)) { + cb.fail({ errMsg: 'rename: fail' }) + return + } + + fs.rename(oldPath, newPath).then(() => { + cb.success({ errMsg: 'rename: ok' }) + }).catch((err) => { + cb.fail({ errMsg: `rename: failedwith error message: ${err.message}, error code: ${err.code}` }) + }) + } + + renameSync (oldPath, newPath) { + // 差异:微信的'' 代指根目录,鸿蒙是不支持访问根目录的 + const res1 = checkPathExistenceSync('renameSync', 'oldPath', oldPath) + if (!res1.isValid) { + throw new Error(res1.errMsg) + } + + const res2 = checkPathSync('renameSync', 'newPath', newPath) + if (!res2.isValid) { + throw new Error(res2.errMsg) + } + + // 若新路径不存在且上级目录也不存在 + const ifAccessNewPath = fs.accessSync(newPath) + if (!ifAccessNewPath && !fs.accessSync(obtainUpperPath(newPath).upperPath)) { + throw new Error(`renameSync: fail no such file or directory, open: ${newPath}`) + } + + // 判断newPath是否存在 若存在且oldPath不等于newPath 则报错 + if (ifAccessNewPath && (oldPath !== newPath)) { + throw new Error('renameSync: fail') + } + + try { + fs.renameSync(oldPath, newPath) + } catch (err) { + throw new Error(`renameSync: ${err.message}`) + } + } + + rmdir ({ dirPath, recursive, success, fail, complete }) { + const cb = new FileCallback({ success, fail, complete }) + + // 将非boolean类型的入参转换为boolean类型 + if (!checkDataType(recursive, false, 'boolean')) { + recursive = Boolean(recursive) + } + + const res = checkPathExistence('rmdir', 'dirPath', dirPath) + if (!res.isValid) { + cb.fail(res.checkMsg) + return + } + + if (!fs.statSync(dirPath).isDirectory()) { + cb.fail({ errMsg: `rmdir: fail no such directory, open: ${dirPath}` }) + return + } + + // recursive为false时,判断该目录下是否有文件 + if (!recursive) { + const filenames = fs.listFileSync(dirPath) + if (filenames.length) { + cb.fail({ errMsg: `rmdir: fail directory not empty` }) + return + } + } + + fs.rmdir(dirPath).then(() => { + console.debug('[AdvanceAPI] rmdir succeed') + cb.success({ errMsg: 'rmdir: ok' }) + }).catch((err) => { + console.error(`[AdvanceAPI] rmdir failed with error message: ${err.message}, error code: ${err.code}`) + cb.fail({ errMsg: 'rmdir: failed' }) + }) + } + + rmdirSync (dirPath, recursive) { + // 将非boolean类型的入参转换为boolean类型 + if (!checkDataType(recursive, false, 'boolean')) { + recursive = Boolean(recursive) + } + + const res = checkPathExistenceSync('rmdirSync', 'dirPath', dirPath) + if (!res.isValid) { + throw new Error(res.errMsg) + } + + // 判断路径是否存在,且不能是文件 + if (!fs.statSync(dirPath).isDirectory()) { + throw new Error(`rmdirSync: fail no such directory, open: ${dirPath}`) + } + + // recursive为false时 且该路径下仍有其他文件 + if (!recursive && (fs.listFileSync(dirPath).length > 0)) { + throw new Error(`rmdirSync: fail directory not empty`) + } + + try { + fs.rmdirSync(dirPath) + } catch (err) { + throw new Error(`rmdirSync: ${err.message}`) + } + } + + truncate ({ filePath, length, success, fail, complete }) { + const cb = new FileCallback({ success, fail, complete }) + const res = checkPathExistence('truncate', 'filePath', filePath) + if (!res.isValid) { + cb.fail(res.checkMsg) + return + } + + // 判断filePath是文件还是目录 + const stat = fs.statSync(filePath) + if (stat.isDirectory()) { + cb.fail({ errMsg: `truncate: fail, illegal operation on a directory, open: ${filePath}` }) + return + } + + if (!checkDataType(length, true, 'number') || length < 0) { + length = DEFAULT_LENGTH // 非number类型 设为默认值DEFAULT_LENGTH ,DEFAULT_LENGTH=0 + } + + fs.truncate(filePath, length).then(() => { + console.debug('[AdvancedAPI] truncate: success, the read length is: %d', length) + cb.success({ errMsg: 'truncate: ok' }) + }).catch((err) => { + console.error(`[AdvancedAPI] truncate: fail with error message: ${err.message}, error code: ${err.code}`) + cb.fail({ errMsg: `truncate: failed with error message: ${err.message}, error code: ${err.code}` }) + }) + } + + truncateSync ({ filePath, length }) { + const res = checkPathExistenceSync('truncateSync', 'filePath', filePath) + if (!res.isValid) { + throw new Error(res.errMsg) + } + + if (fs.statSync(filePath).isDirectory()) { + throw new Error(`truncateSync: fail, illegal operation on a directory, open: ${filePath}`) + } + + if (!checkDataType(length, true, 'number') || length < 0) { + length = DEFAULT_LENGTH // 非number类型 设为默认值DEFAULT_LENGTH ,DEFAULT_LENGTH=0 + } + + try { + fs.truncateSync(filePath, length) + } catch (err) { + throw new Error(`truncateSync: ${err.message}`) + } + } + + /** + * 获取文件信息 + * @param {string} filePath - 本地文件路径 + * @param {function} success - 接口调用成功的回调函数 + * @param {function} fail - 接口调用失败的回调函数 + * @param {function} complete - 接口调用结束的回调函数(调用成功、失败都会执行) + */ + getFileInfo ({ filePath, success, fail, complete }) { + const cb = new FileCallback({ success, fail, complete }) + filePath = isSandboxPath(filePath) ? switchInternalToHapSandBox(filePath) : filePath + if (!filePath || !checkDataType(filePath, true, 'string')) { + cb.fail({ errMsg: 'getFileInfo:fail invalid filePath ' }) + return + } + if (!fs.accessSync(filePath)) { + cb.fail({ errMsg: 'getFileInfo: fail no such file or directory : ' + filePath }) + return + } + const stat = fs.statSync(filePath) + cb.success({ size: stat.size, errMsg: 'getFileInfo:ok ' }) + return + } +} diff --git a/ohos/AdvancedAPI_OHOS/src/advancedApi/module/ASFile/index.js b/ohos/AdvancedAPI_OHOS/src/advancedApi/module/ASFile/index.js new file mode 100644 index 0000000000..1fc7261e1d --- /dev/null +++ b/ohos/AdvancedAPI_OHOS/src/advancedApi/module/ASFile/index.js @@ -0,0 +1,212 @@ +import { context } from '../../../base/bridge/abilityBase' +import { FileioBase } from '../../../base/bridge/fileioBase' +import { SecurityBase } from '../../../base/bridge/securityBase' +import { getFdFromUriOrSandBoxPath, isSandboxPath, switchInternalToHapSandBox } from '../../util' +import FileSystemManager from './FileSystemManager' +import util from '@ohos.util' +import fileuri from '@ohos.file.fileuri' +import { ErrorCode } from '../../../base/util/ErrorCode' + +export default class ASFile { + constructor() { + this.DIGESTALGORITHM_VALUES = ['MD5', 'SHA1'] + // 文件保存路径:/data/storage/el2/base/haps/advancedDEMO/files/saveFiles + this.saveFileDir = context.filesDir + '/saveFiles' + this.fileSystemManager = new FileSystemManager() + this.init() + } + + init () { + try { + FileioBase.ohosMkdirSync(this.saveFileDir) + } catch (error) { + console.debug('[AdvancedAPI] %s 已存在', this.saveFileDir) + } + } + + /** + * 保存文件到本地 + * @param {string} tempFilePath - 需要保存的文件的临时路径 + * @param {function} success - 返回文件的保存路径,res = {savedFilePath: '文件的保存路径'} + * @param {function} fail - 接口调用失败的回调函数 + * @param {function} complete - 接口调用结束的回调函数(调用成功、失败都会执行) + */ + saveFile (params) { + return new Promise(async (resolve, reject) => { + const { tempFilePath } = params + if (!tempFilePath) { + console.error('[AdvancedAPI] invalid tempFilePath.') + reject(['tempFilePath is required.', ErrorCode.PARAMETER_ERROR]) + return + } + try { + const fileName = tempFilePath.substr(tempFilePath.lastIndexOf('/')) + const fileType = fileName && fileName.split('.').pop() + let newFileName = new Date().getTime() + if (fileType) { + newFileName += `.${fileType}` + } + const fileUri = isSandboxPath(tempFilePath) ? + fileuri.getUriFromPath(switchInternalToHapSandBox(tempFilePath)) : tempFilePath + const fd = getFdFromUriOrSandBoxPath(fileUri) + const destPath = this.saveFileDir + '/' + newFileName // 保存路径 + FileioBase.ohosCopy(fd, destPath).then(() => { + console.debug('[AdvancedAPI] saveFile succeed') + resolve({ savedFilePath: destPath }) + }).catch((err) => { + console.error('[AdvancedAPI] saveFile failed with error message: ' + err.message + ', error code: ' + err.code) + reject([err.message, ErrorCode.IO_ERROR]) + }) + } catch (err) { + console.error('[AdvancedAPI] tempFilePath does not exist') + reject(['tempFilePath does not exist', ErrorCode.PARAMETER_ERROR]) + } + }) + } + + /** + * 获取本地已保存的文件列表 + * @param {function} success - 接口调用成功的回调函数 + * @param {function} fail - 接口调用失败的回调函数 + * @param {function} complete - 接口调用结束的回调函数(调用成功、失败都会执行) + */ + getSavedFileList () { + return new Promise((resolve, reject) => { + const dir = FileioBase.ohosOpendirSync(this.saveFileDir) + const fileList = [] + const dirent = dir.ohosReadsync() + for (let i = 0; i < dirent.length; i++) { + const filePath = `${this.saveFileDir}/${dirent[0]}` + const stat = FileioBase.ohosStatSync(filePath) + if (stat.isFile()) { + const fileItem = { + filePath: filePath, + createTime: stat.mtime, + size: stat.size + } + fileList.push(fileItem) + } + } + resolve({ fileList }) + }) + } + + /** + * 获取本地文件的文件信息。此接口只能用于获取已保存到本地的文件。 + * @param {string} filePath - 文件路径 + * @param {function} success - 接口调用成功的回调函数 + * @param {function} fail - 接口调用失败的回调函数 + * @param {function} complete - 接口调用结束的回调函数(调用成功、失败都会执行) + */ + getSavedFileInfo (params) { + return new Promise((resolve, reject) => { + const { filePath } = params + if (!filePath) { + console.error('[AdvancedAPI] filePath is required.') + reject(['filePath is required', ErrorCode.PARAMETER_ERROR]) + return + } + const fileUri = isSandboxPath(filePath) ? + fileuri.getUriFromPath(switchInternalToHapSandBox(filePath)) : filePath + const fd = getFdFromUriOrSandBoxPath(fileUri) + const stat = FileioBase.ohosStatSync(fd) + const fileInfo = { + createTime: stat.mtime, + size: stat.size, + errMsg: 'getSavedFileInfo:ok' + } + resolve(fileInfo) + }) + } + + /** + * 删除本地存储的文件。 + * @param {string} filePath - 文件路径 + * @param {function} success - 接口调用成功的回调函数 + * @param {function} fail - 接口调用失败的回调函数 + * @param {function} complete - 接口调用结束的回调函数(调用成功、失败都会执行) + */ + removeSavedFile (params) { + return new Promise((resolve, reject) => { + const { filePath } = params + if (!filePath) { + console.error('[AdvancedAPI] filePath is required.') + reject(['filePath is required', ErrorCode.PARAMETER_ERROR]) + return + } + try { + const destPath = isSandboxPath(filePath) ? switchInternalToHapSandBox(filePath) : filePath + FileioBase.ohosUnlinkSync(destPath) + resolve('success') + } catch (err) { + reject(['removeSavedFile is fail', ErrorCode.IO_ERROR]) + } + }) + } + + /** + * 获取文件信息 + * @param {string} filePath - 本地文件路径 + * @param {string} digestAlgorithm - 计算文件摘要的算法,可取值 md5、sha1。 + * @param {function} success - 接口调用成功的回调函数 + * @param {function} fail - 接口调用失败的回调函数 + * @param {function} complete - 接口调用结束的回调函数(调用成功、失败都会执行) + */ + getFileInfo (params) { + return new Promise((resolve, reject) => { + const { filePath } = params + let { digestAlgorithm = 'MD5' } = params + if (!filePath) { + console.error('[AdvancedAPI] filePath is required.') + reject(['filePath is required', ErrorCode.PARAMETER_ERROR]) + return + } + if (typeof digestAlgorithm === 'string') { + digestAlgorithm = digestAlgorithm.toUpperCase() + } + + if (!this.DIGESTALGORITHM_VALUES.includes(digestAlgorithm)) { + console.error('[AdvancedAPI] digestAlgorithm is invalid.') + digestAlgorithm = 'MD5' + } + try { + const fileUri = isSandboxPath(filePath) ? + fileuri.getUriFromPath(switchInternalToHapSandBox(filePath)) : filePath + const fd = FileioBase.ohosOpenSync(fileUri, 0o2).fd + const stat = FileioBase.ohosStatSync(fd) + const buf = new ArrayBuffer(stat.size) + FileioBase.ohosReadSync(fd, buf) + SecurityBase.rsa(digestAlgorithm, { data: new Uint8Array(buf) }).then(resultBuf => { + const textDecoder = new util.TextDecoder('utf-8', { ignoreBOM: true }) + resolve({ size: stat.size, digest: textDecoder.decodeWithStream(resultBuf, { stream: false }) }) + }) + } catch (err) { + console.error(`[AdvancedAPI] getFileInfo fail err = ${JSON.stringify(err)}`) + reject(['getFileInfo is fail', ErrorCode.IO_ERROR]) + } + }) + } + + /** + * 新开页面打开文档,支持格式:doc, xls, ppt, pdf, docx, xlsx, pptx。 + * @param {string} filePath - 文件路径,可通过 downFile 获得 + * @param {string} fileType - 文件类型,指定文件类型打开文件,有效值 doc, xls, ppt, pdf, docx, xlsx, pptx,支付宝小程序仅支持pdf + * @param {boolean} showMenu - 右上角是否有可以转发分享的功能,不支持 + * @param {function} success - 接口调用成功的回调函数 + * @param {function} fail - 接口调用失败的回调函数 + * @param {function} complete - 接口调用结束的回调函数(调用成功、失败都会执行) + */ + openDocument (params) { + return new Promise((resolve, reject) => { + // eslint-disable-next-line no-unused-vars + const { filePath, fileType, showMenu = false } = params + if (showMenu) { + console.error('[AdvancedAPI] showMenu do not support.') + } + }) + } + + getFileSystemManager () { + return this.fileSystemManager + } +} diff --git a/ohos/AdvancedAPI_OHOS/src/advancedApi/module/ASFile/util.js b/ohos/AdvancedAPI_OHOS/src/advancedApi/module/ASFile/util.js new file mode 100644 index 0000000000..986e683e21 --- /dev/null +++ b/ohos/AdvancedAPI_OHOS/src/advancedApi/module/ASFile/util.js @@ -0,0 +1,280 @@ +import fs from '@ohos.file.fs' +import { checkDataType } from '../../../base/util/checkDataType' + +const openMode = fs.OpenMode +const ERROR = { + PARAMETER_ERROR: 1001 +} + +export const modeReflect = { + 'ax': 'a', + 'ax+': 'a+', + 'wx': 'w', + 'wx+': 'w+' +} + +const ENCODING = [ + 'utf8', + 'utf-8', + 'ascii', + 'base64', + 'binary', + 'hex', + 'ucs2', + 'ucs-2', + 'utf16le', + 'utf-16le', + 'latin1', +] + +export function getOpenMode (flag) { + let mode + switch (flag) { + case 'a': + mode = openMode.CREATE | openMode.APPEND + break + case 'a+': + mode = openMode.CREATE | openMode.READ_WRITE | openMode.APPEND + break + case 'as': + mode = openMode.SYNC | openMode.CREATE | openMode.APPEND + break + case 'as+': + mode = openMode.SYNC | openMode.CREATE | openMode.READ_WRITE | openMode.APPEND + break + case 'r': + mode = openMode.READ_ONLY + break + case 'r+': + mode = openMode.READ_WRITE + break + case 'w': + mode = openMode.CREATE | openMode.WRITE_ONLY | openMode.TRUNC + break + case 'w+': + mode = openMode.CREATE | openMode.READ_WRIT | openMode.TRUNC + break + } + return mode +} + +// 获取文件的类型码并返回 +export function getFileTypeMode (stat) { + if (stat.isBlockDevice()) { + return 0o060000 + } + if (stat.isCharacterDevice()) { + return 0o020000 + } + if (stat.isDirectory()) { + return 0o040000 + } + if (stat.isFIFO()) { + return 0o010000 + } + if (stat.isFile()) { + return 0o100000 + } + if (stat.isSocket()) { + return 0o140000 + } + if (stat.isSymbolicLink()) { + return 0o120000 + } +} + +// 递归创建目录 +export function mkdirRecursive (path, dirNames) { + const curDirName = dirNames.shift() + if (!path && !curDirName) { + path = '' + } else { + path = path + '/' + curDirName + } + if (!curDirName) { + if (dirNames.length > 0) { + mkdirRecursive(path, dirNames) + } + return + } + + // 如果目录存在 + if (fs.accessSync(path)) { + if (dirNames.length > 0) { + mkdirRecursive(path, dirNames) + } + } else { + // 目录不存在 + fs.mkdirSync(path) + if (dirNames.length > 0) { + mkdirRecursive(path, dirNames) + } + } +} + +export function ohosMkdir (dirPath, cb) { + fs.mkdir(dirPath) + .then(() => { + cb.success({ errMsg: 'mkdir: ok' }) + }) + .catch((err) => { + cb.fail({ + errMsg: `mkdir: failed with error message: ${err.message}, error code: ${err.code}` + }) + }) +} + +// 获取目录路径 +export function obtainUpperPath (inputPath) { + const index = inputPath.lastIndexOf('/') + const upperPath = inputPath.substring(0, index) + return { index, upperPath } +} + +export function obtainFileName (inputPath) { + const index = inputPath.lastIndexOf('/') + let fileName = inputPath.substring(index) + + // 处理' ../test.txt/ '的情况 + if (inputPath.endsWith('/')) { + fileName = inputPath.substring(inputPath.lastIndexOf('/', inputPath.length - 2) + 1, inputPath.length - 1) + } + + return { index, fileName } +} + +export function checkFd (methodName, fd) { + let checkMsg = {} + const isValid = false + if (!checkDataType(fd, true, 'string')) { + checkMsg = { + errno: ERROR.PARAMETER_ERROR, + errMsg: `${methodName}: fail, invalid fd` + } + return { checkMsg, isValid } + } + + const transFdToNum = Number(fd) + if (fd === '' || isNaN(transFdToNum)) { + checkMsg = { errMsg: `${methodName}: fail, invalid fd` } + return { checkMsg, isValid } + } + return { isValid: true, fd: transFdToNum } +} + +export function checkFdSync (methodName, fd) { + const isValid = false + if (!checkDataType(fd, true, 'string')) { + return { + errMsg: `${methodName}: fail invalid fd`, + isValid + } + } + + const transFdToNum = Number(fd) + if (fd === '' || isNaN(transFdToNum)) { + return { + errMsg: `${methodName}: fail invalid fd`, + isValid + } + } + + return { isValid: true, fd: transFdToNum } +} + +export function checkEncoding (methodName, encoding) { + if (!encoding) { + return { isValid: true } + } + const isValid = false + if (!checkDataType(encoding, false, 'string')) { + const checkMsg = `${methodName}:fail invalid encoding: ${encoding}` + return { checkMsg, isValid } + } + if (!ENCODING.includes(encoding)) { + const checkMsg = `${methodName}:fail Unknown encoding: ${encoding}` + return { checkMsg, isValid } + } + return { isValid: true } +} + +// 检验路径的合法性:string 和 空串 +export function checkPath (methodName, pathName, path) { + let checkMsg = {} + const isValid = false + if (!checkDataType(path, true, 'string')) { + checkMsg = { + errno: ERROR.PARAMETER_ERROR, + errMsg: `${methodName}: fail, ${pathName} should be String instead of: ${typeof path}` + } + return { checkMsg, isValid } + } + + if (path === '') { + // eslint-disable-next-line no-useless-escape + checkMsg = { errMsg: `${methodName}: fail permission denied, open:\'\'` } + return { checkMsg, isValid } + } + + // 校验通过 + return { isValid: true } +} + +// 检验路径的合法性:string 、空串 、必须存在 +export function checkPathExistence (methodName, pathName, path) { + let checkMsg = {} + const isValid = false + if (!checkDataType(path, true, 'string')) { + checkMsg = { + errno: ERROR.PARAMETER_ERROR, + errMsg: `${methodName}: fail, ${pathName} should be String instead of: ${typeof path}` + } + return { checkMsg, isValid } + } + + if (path === '') { + // eslint-disable-next-line no-useless-escape + checkMsg = { errMsg: `${methodName}: fail permission denied, open:\'\'` } + return { checkMsg, isValid } + } + + // 判断srcPath路径是否存在 + if (!fs.accessSync(path)) { + checkMsg = { errMsg: `${methodName}: fail no such file or directory, open: ${path}` } + return { checkMsg, isValid } + } + // 校验通过 + return { isValid: true } +} + +export function checkPathSync (methodName, pathName, path) { + const isValid = false + if (path === '' || !checkDataType(path, true, 'string')) { + return { + errMsg: `${methodName}: failed, ${pathName} should be a non-empty string`, + isValid + } + } + + return { isValid: true } +} + +export function checkPathExistenceSync (methodName, pathName, path) { + const isValid = false + if (path === '' || !checkDataType(path, true, 'string')) { + return { + errMsg: `${methodName}: failed, ${pathName} should be a non-empty string`, + isValid + } + } + + // 判断Path是否存在 + if (!fs.accessSync(path)) { + return { + errMsg: `${methodName}: fail no such file or directory: ${path}`, + isValid + } + } + + return { isValid: true } +} diff --git a/ohos/AdvancedAPI_OHOS/src/advancedApi/module/ASGyroscope/index.js b/ohos/AdvancedAPI_OHOS/src/advancedApi/module/ASGyroscope/index.js new file mode 100644 index 0000000000..f29f5b557c --- /dev/null +++ b/ohos/AdvancedAPI_OHOS/src/advancedApi/module/ASGyroscope/index.js @@ -0,0 +1,68 @@ +/** + * Copyright (c) Huawei Technologies Co., Ltd. 2023-2023. All rights reserved. + * Description: Advanced API gyroscope + * Author: 00430169 + * Create: 7/4/2023 + * Notes: N/A + */ + +import { OhosSensorBase } from '../../../base/bridge/sensorBase' +import { ErrorCode } from '../../../base/util/ErrorCode' + +const intervalType = [ + { label: 'game', value: 20000000 }, + { label: 'ui', value: 60000000 }, + { label: 'normal', value: 200000000 } +] + +export default class ASGyroscope { + constructor () { + this.callBackGyroscopeSet = new Set() + } + + onGyroscopeChange (callback) { + return new Promise((resolve, reject) => { + if (typeof callback !== 'function') { + reject('param is invalid.', ErrorCode.PARAMETER_ERROR) + return + } + if (this.callBackGyroscopeSet.has(callback)) { + reject('param is invalid.', ErrorCode.PARAMETER_ERROR) + } else { + this.callBackGyroscopeSet.add(callback) + resolve() + } + }) + } + + startGyroscope (object = {}) { + return new Promise((resolve, reject) => { + let value = intervalType.find(i => i.label === 'normal').value + if (object.interval && typeof object.interval === 'string') { + const target = intervalType.find(i => i.label === object.interval) + if (target) { + value = target.value + } + } + + OhosSensorBase.ohosSubscribeGyroscope({ intervalValue: value, callback: (data) => { + const res = { + x: data.x, + y: data.y, + z: data.z + } + for (const cb of this.callBackGyroscopeSet.keys()) { + cb(res) + } + } }) + resolve() + }) + } + + stopGyroscope () { + return new Promise((resolve, reject) => { + OhosSensorBase.ohosUnsubscribeGyroscope() + resolve() + }) + } +} diff --git a/ohos/AdvancedAPI_OHOS/src/advancedApi/module/ASImage/index.js b/ohos/AdvancedAPI_OHOS/src/advancedApi/module/ASImage/index.js new file mode 100644 index 0000000000..edce1381cb --- /dev/null +++ b/ohos/AdvancedAPI_OHOS/src/advancedApi/module/ASImage/index.js @@ -0,0 +1,345 @@ +import { ErrorCode } from '../../../base/util/ErrorCode' +import { FileioBase } from '../../../base/bridge/fileioBase' +import { MediaLibraryBase } from '../../../base/bridge/mediaLibraryBase' +import { WantConstantBase } from '../../../base/bridge/wantConstantBase' +import { context } from '../../../base/bridge/abilityBase' +import { + isFileUri, + getFdFromUriOrSandBoxPath, + getFileAssetFromUri, + isSandboxPath, + switchInternalToHapSandBox, + saveMedia, +} from '../../util/index' +import bundleManager from '@ohos.bundle.bundleManager' +import image from '@ohos.multimedia.image' +import { Base64 } from 'js-base64' +import picker from '@ohos.file.picker' +import fs from '@ohos.file.fs' +import photoAccessHelper from '@ohos.file.photoAccessHelper' +import fileUri from '@ohos.file.fileuri' + +// 启动图库模式 +// eslint-disable-next-line no-unused-vars +const PHOTO = { + SINGLE: 'singleselect', + MULTIPLE: 'multipleselect', + PREVIEW: 'photodetail', +} + +// eslint-disable-next-line no-unused-vars +const ORI = { + 0: 'up', + 90: 'right', + 180: 'down', + 270: 'left', +} + +// eslint-disable-next-line no-unused-vars +const MEDIATYPE = ['FILE', 'IMAGE', 'VIDEO', 'AUDIO'] +export default class ASImage { + chooseImage(params) { + if (!params) { + params = {} + } + return new Promise(async (resolve, reject) => { + const permission = await MediaLibraryBase.getPermissions() + if (permission.perNum === -1) { + return reject(['permission fail', ErrorCode.USER_REJECT, permission.perNum, permission.dialogShownResults]) + } + if (params.count && typeof (params.count) !== 'number') { + return reject(['chooseImage:fail parameter `count`. Expected Number with value NaN, ' + + 'got String with value "' + params.count + '".', ErrorCode.PARAMETER_ERROR]) + } + if (params.count < 1) { + params.count = 9 + } + let uris = [] + if (params.sourceType && params.sourceType.length === 1 && params.sourceType.includes('camera')) { + // 单独指定使用相机 + const info = await bundleManager.getBundleInfoForSelf(bundleManager.BundleFlag.GET_BUNDLE_INFO_DEFAULT) + const data = await context.startAbilityForResult({ + action: WantConstantBase.getAction('ACTION_IMAGE_CAPTURE'), + parameters: { + uri: 'capture', + callBundleName: info.name, + }, + }) + if (data.resultCode === 0) { + uris = [data.want.parameters.resourceUri] + if (!data.want.parameters.resourceUri) { + return + } + } else { + return reject(['Failed to pull up camera app', ErrorCode.SERVICE_UNAVIALABLE]) + } + } else { + // 拉去图库应用 + const PhotoSelectOptions = new picker.PhotoSelectOptions() + PhotoSelectOptions.MIMEType = picker.PhotoViewMIMETypes.IMAGE_TYPE + PhotoSelectOptions.maxSelectNumber = params.count + const photoPicker = new picker.PhotoViewPicker() + const photoSelectResult = await photoPicker.select(PhotoSelectOptions) + uris = photoSelectResult.photoUris + } + + if (!uris) { + return reject(['get uri fail', ErrorCode.SERVICE_UNAVIALABLE]) + } else if (uris === 'cancel') { + // 取消时不触发success和fail + return + } + + const tempFilePaths = [] + const tempFiles = [] + for (let i = 0; i < uris.length; i++) { + let compress + if (params.sizeType && params.sizeType.length === 1 && params.sizeType.includes('compressed')) { + compress = await this.compressImage({ src: uris[i] }) + if (compress.tempFilePath) { + tempFilePaths.push(compress.tempFilePath) + tempFiles.push({ + path: compress.tempFilePath, + size: compress.tempSize, + name: compress.tempName, + type: compress.tempFilePath.split('.').pop(), + }) + } + } else { + const asset = await getFileAssetFromUri(uris[i]) + tempFilePaths.push(uris[i]) + tempFiles.push({ + path: uris[i], + size: asset.size, + name: asset.displayName, + type: asset.displayName.split('.').pop(), + }) + } + } + return resolve({ + tempFilePaths, tempFiles, + }) + }) + } + + getImageInfo(params) { + return new Promise(async (resolve, reject) => { + try { + const ORI = { + 0: 'up', + 90: 'right', + 180: 'down', + 270: 'left', + } + const uri = params.src + if (isFileUri(uri)) { + const asset = await getFileAssetFromUri(uri) + const orientation = ORI[asset.orientation] + return resolve({ + width: asset.width, + height: asset.height, + path: uri, + orientation, + type: asset.displayName.split('.').pop(), + }) + } else if (isSandboxPath(uri)) { + const imageSourceApi = image.createImageSource(switchInternalToHapSandBox(uri)) + const orientation = 'up' + const type = uri.split('.').pop() + const imageInfo = await imageSourceApi.getImageInfo() + return resolve({ + width: imageInfo.size.width, + height: imageInfo.size.height, + path: params.src, + orientation, + type, + }) + } else { + return reject(['get uri fail', ErrorCode.SERVICE_UNAVIALABLE]) + } + } catch (err) { + return reject(['get uri fail', ErrorCode.SERVICE_UNAVIALABLE]) + } + }) + } + + saveImageToPhotosAlbum(params) { + return new Promise(async (resolve, reject) => { + try { + const filePath = params.filePath + if (typeof filePath !== 'string') { + return reject(['filePath format is not supported.', ErrorCode.PARAMETER_ERROR]) + } + if (isFileUri(filePath)) { + const uri = filePath + const fd = getFdFromUriOrSandBoxPath(uri) + const stat = fs.statSync(fd) + const size = stat.size + const buf = new ArrayBuffer(size) + FileioBase.ohosReadSync(fd, buf) + const fileAsset = await getFileAssetFromUri(uri) + const displayName = 'IMAGE_' + new Date().getTime() + '_' + fileAsset.displayName + // uri = fileUri.getUriFromPath(uri) + const imageUri = await saveMedia(photoAccessHelper.PhotoType.IMAGE, displayName, uri, buf) + resolve({ path: imageUri }) + return + } else if (isSandboxPath(filePath)) { + let uri = filePath + // 对于internal开头的路径,需要转换 + if (uri.startsWith('internal://')) { + uri = switchInternalToHapSandBox(filePath) + } + if (!fs.accessSync(uri)) { + reject(['saveImageToPhotosAlbum fail, src not exist.', ErrorCode.PARAMETER_ERROR]) + return + } + const file = fs.openSync(uri, fs.OpenMode.READ_ONLY) + if (!file) { + reject(['saveImageToPhotosAlbum fail, src not exist.', ErrorCode.PARAMETER_ERROR]) + return + } + const fd = file.fd + // 根据文件大小定义空arrayBuffer用来写入文件 + const stat = fs.statSync(uri) + const size = stat.size + const buf = new ArrayBuffer(size) + // 读取传入文件信息到缓冲区 + FileioBase.ohosReadSync(fd, buf) + // 获取文件显示名 + let displayName = 'IMAGE_' + new Date().getTime() + '_' + uri.split('/').splice(-1, 1).toString() + // 对于internal这种有可能结尾不带.jpg的情况,需要加上.jpg + if (!displayName.includes('.')) { + displayName += '.jpg' + } + // 获取file://应用沙箱路径 + uri = fileUri.getUriFromPath(uri) + const imageUri = await saveMedia(photoAccessHelper.PhotoType.IMAGE, displayName, uri, buf) + resolve({ path: imageUri }) + return + } else if (filePath.startsWith('data:image/')) { + const base64Array = filePath.split(';') + if (base64Array.length === 2 && base64Array[1].startsWith('base64')) { + const imageType = base64Array[0].replace('data:image/', '') + const imageData = Base64.atob(filePath.split(',')[1]) + const displayName = 'IMAGE_' + new Date().getTime() + '.' + imageType + const arrayBuffer = new ArrayBuffer(imageData.length) + const ia = new Uint8Array(arrayBuffer) + for (let i = 0; i < imageData.length; i++) { + ia[i] = imageData.charCodeAt(i) + } + // 获取file://应用沙箱路径 + const uri = fileUri.getUriFromPath(filePath) + const imageUri = await saveMedia(photoAccessHelper.PhotoType.IMAGE, displayName, uri, ia.buffer) + resolve({ path: imageUri }) + return + } + } + reject(['filePath format is not supported.', ErrorCode.PARAMETER_ERROR]) + } catch (error) { + console.error(`[AdvancedAPI] saveImageToPhotosAlbum is fail!errMsg:${JSON.stringify(error)}`) + } + }) + } + + /** + * 图片压缩 现在支持两种路径,沙箱路径或者公共文件URI,输出的是沙箱路径的临时文件目录 + * @param params + * @returns {Promise} + */ + compressImage(params) { + return new Promise(async (resolve, reject) => { + const src = switchInternalToHapSandBox(params.src) + const fileName = src.split('/').pop() || '' + const suffix = fileName.indexOf('.') >= 0 ? (params.src.toLowerCase().split('.').pop() || 'jpg') : 'jpg' + let quality = params.quality || 80 + const permission = await MediaLibraryBase.getPermissions() + if (permission.perNum === -1) { + return reject(['permission fail', ErrorCode.USER_REJECT, permission.perNum, permission.dialogShownResults]) + } + if (quality && typeof (quality) !== 'number') { + return reject(['compressImage fail, input parameter quality is illegal.', ErrorCode.PARAMETER_ERROR]) + } + if (quality > 100 || quality < 0) { + quality = 80 + } + try { + let fd + const supportTypes = ['jpg', 'png', 'webp', 'jpeg'] + if (isSandboxPath(src)) { + if (!fs.accessSync(src)) { + reject(['compressImage fail, src not exist.', ErrorCode.PARAMETER_ERROR]) + return + } + const file = fs.openSync(src, fs.OpenMode.READ_ONLY) + if (!file) { + reject(['compressImage fail, src not exist.', ErrorCode.PARAMETER_ERROR]) + return + } + fd = file.fd + } else if (isFileUri(src)) { + fd = getFdFromUriOrSandBoxPath(src) + } + if (supportTypes.includes(suffix)) { + const arrayBuf = await this.getArrayBuffer(quality, fd, suffix, params.compressHeight, params.compressedWidth) + const dirName = new Date().getTime() + const jpgName = 'IMAGE_' + dirName + const tmpPath = context.tempDir + '/' + dirName + '/' + jpgName + '.' + `${params.src.toLowerCase().split('.').pop()}` + let size + try { + await fs.mkdir(context.tempDir + '/' + dirName) + fs.openSync(tmpPath, fs.OpenMode.CREATE) + const fileOpen = fs.openSync(tmpPath, fs.OpenMode.READ_WRITE) + FileioBase.ohosWriteSync(fileOpen.fd, arrayBuf) + // 获取临时文件的大小 + const tempFile = fs.openSync(tmpPath, fs.OpenMode.READ_ONLY) + const stat = fs.statSync(tempFile.fd) + size = stat.size + fs.closeSync(fileOpen) + } catch (error) { + console.info(`${JSON.stringify(error)}`) + } + resolve({ + tempFilePath: tmpPath, + tempSize: size, + tempName: jpgName, + }) + } + } catch (error) { + reject(['compressImage fail, src not exist.', ErrorCode.PARAMETER_ERROR]) + } + }) + } + + getArrayBuffer = async (quality, fd, suffix, height, width) => { + if (height !== undefined || width !== undefined) { + const widthSize = width || height || 0 + const imageSourceApi = image.createImageSource(fd) + const imagePackerApi = image.createImagePacker() + const imageInfo = await imageSourceApi.getImageInfo() + const rate = imageInfo.size.width / width + const pixelMap = await imageSourceApi.createPixelMap({ + desiredSize: { + width: widthSize, + // height: heightSize + height: imageInfo.size.height / rate // width和height必须同时存在,只有width时,compressedWidth和compressHeight不奏效 + } + }) + const packOpts = { format: `image/jpeg`, quality } + const arrayBuf = await imagePackerApi.packing(pixelMap, packOpts) + return arrayBuf + } else { + const imageSourceApi = image.createImageSource(fd) // 创建图片源实例 + const imagePackerApi = image.createImagePacker() // 创建ImagePacker实例 + const packOpts = { format: `image/jpeg`, quality } // format目标格式 + const imageInfo = await imageSourceApi.getImageInfo() + const pixelMap = await imageSourceApi.createPixelMap({ + desiredSize: { + width: imageInfo.size.width, + height: imageInfo.size.height + } + }) + const arrayBuf = await imagePackerApi.packing(pixelMap, packOpts) + return arrayBuf + } + } +} diff --git a/ohos/AdvancedAPI_OHOS/src/advancedApi/module/ASInterceptor/index.js b/ohos/AdvancedAPI_OHOS/src/advancedApi/module/ASInterceptor/index.js new file mode 100644 index 0000000000..54a390fd27 --- /dev/null +++ b/ohos/AdvancedAPI_OHOS/src/advancedApi/module/ASInterceptor/index.js @@ -0,0 +1,131 @@ +export default class ASInterceptor { + constructor () { + this.apiLists = {} + this.globals = [] + } + + checkApiName (apiName) { + if (apiName === 'addInterceptor' + || apiName === 'removeInterceptor') { + return false + } + return true + } + + invoke (apiName, args) { + // 1. 触发全局拦截器 + this.globals.forEach(option => { + const invoke = option.invoke + if (typeof invoke === 'function') { + invoke(...args) + } + }) + // 2. 触发api拦截器 + const apiOptions = this.apiLists[apiName] || [] + apiOptions.forEach(option => { + const invoke = option.invoke + if (typeof invoke === 'function') { + invoke(...args) + } + }) + } + + success (apiName, args) { + const tasks = [] + // 1. 触发全局拦截器 + this.globals.forEach(option => { + const success = option.success + if (typeof success === 'function') { + tasks.push(success) + } + }) + // 2. 触发api拦截器 + const apiOptions = this.apiLists[apiName] || [] + apiOptions.forEach(option => { + const success = option.success + if (typeof success === 'function') { + tasks.push(success) + } + }) + + if (tasks.length) { + const methodArgs = args && JSON.parse(JSON.stringify(args)) + tasks.forEach(task => { + task(...methodArgs) + }) + return methodArgs + } + } + + fail (apiName, args) { + const tasks = [] + // 1. 触发全局拦截器 + this.globals.forEach(option => { + const fail = option.fail + if (typeof fail === 'function') { + tasks.push(fail) + } + }) + // 2. 触发api拦截器 + const apiOptions = this.apiLists[apiName] || [] + apiOptions.forEach(option => { + const fail = option.fail + if (typeof fail === 'function') { + tasks.push(fail) + } + }) + + if (tasks.length) { + const methodArgs = args && JSON.parse(JSON.stringify(args)) + tasks.forEach(task => { + task(...methodArgs) + }) + return methodArgs + } + } + + complete (apiName, args) { + const tasks = [] + // 1. 触发全局拦截器 + this.globals.forEach(option => { + const complete = option.complete + if (typeof complete === 'function') { + tasks.push(complete) + } + }) + // 2. 触发api拦截器 + const apiOptions = this.apiLists[apiName] || [] + apiOptions.forEach(option => { + const complete = option.complete + if (typeof complete === 'function') { + tasks.push(complete) + } + }) + + if (tasks.length) { + const methodArgs = args && JSON.parse(JSON.stringify(args)) + tasks.forEach(task => { + task(...methodArgs) + }) + return methodArgs + } + } + + returnValue (apiName, args) { + // 1. 触发全局拦截器 + this.globals.forEach(option => { + const returnValue = option.returnValue + if (typeof returnValue === 'function') { + returnValue(args) + } + }) + // 2. 触发api拦截器 + const apiOptions = this.apiLists[apiName] || [] + apiOptions.forEach(option => { + const returnValue = option.returnValue + if (typeof returnValue === 'function') { + returnValue(args) + } + }) + } +} diff --git a/ohos/AdvancedAPI_OHOS/src/advancedApi/module/ASKeyboard/index.js b/ohos/AdvancedAPI_OHOS/src/advancedApi/module/ASKeyboard/index.js new file mode 100644 index 0000000000..853a536913 --- /dev/null +++ b/ohos/AdvancedAPI_OHOS/src/advancedApi/module/ASKeyboard/index.js @@ -0,0 +1,112 @@ +/** + * Copyright (c) Huawei Technologies Co., Ltd. 2023-2023. All rights reserved. + * Description: advanced keyboard api + * Create: 04/10/2023 + * Notes: + */ +import inputMethod from '@ohos.inputMethod' +import window from '@ohos.window' +import { DisplayBase } from '../../../base/bridge/displayBase' + +// AS API class +export default class ASKeyboard { + /** + * constructor function, init callback map + */ + constructor () { + this.changeCallback = new Map() + } + + /** + * hide software keyboard + * need system permission ohos.permission.CONNECT_IME_ABILITY + */ + hideKeyboard() { + return new Promise((resolve, reject) => { + try { + const inputMethodController = inputMethod.getController() + inputMethodController.hideTextInput().then(() => { + console.debug('[AdvancedAPI] Succeeded in hiding softKeyboard.') + resolve() + }).catch((err) => { + console.error('[AdvancedAPI] Failed to hideSoftKeyboard: ' + JSON.stringify(err)) + reject() + }) + } catch (exception) { + console.error('[AdvancedAPI] Failed to get inputMethod Controller. Cause: ' + JSON.stringify(exception)) + reject() + } + }) + } + + /** + * subscribe keyboard height change event + * Callback + * @obj params height {Number}: keyboard height + */ + onKeyboardHeightChange(callback) { + if (!callback) { + console.error('[AdvancedAPI] params illegal, empty callback') + return + } + + try { + window.getLastWindow(globalThis.abilityContext).then((data) => { + this.windowClass = data + const { + densityPixels: devicePixelRatio, + } = DisplayBase.ohosGetDisplay() + + const heightChangeCallback = function (data) { + // ohos notify twice when keyboard popup + callback({ height: Math.round(data / devicePixelRatio) }) + } + if (!this.changeCallback.has(callback)) { + this.changeCallback.set(callback, heightChangeCallback) + } + console.info('[AdvancedAPI] Succeeded in obtaining the top window. Listen to keyboard height change') + try { + this.windowClass.on('keyboardHeightChange', this.changeCallback.get(callback)) + } catch (exception) { + console.error('[AdvancedAPI] Failed to enable the listener for keyboard height changes. Cause: ' + JSON.stringify(exception)) + } + }).catch((err) => { + console.error('[AdvancedAPI] Failed to obtain the top window. Cause: ' + JSON.stringify(err)) + }) + } catch (exception) { + console.error('[AdvancedAPI] Failed to obtain the top window. Cause: ' + JSON.stringify(exception)) + } + } + + /** + * unsubscribe keyboard height change event + * remove all if callback is null, otherwise remove the specialized callback + */ + offKeyboardHeightChange(callback) { + try { + window.getLastWindow(globalThis.abilityContext).then((data) => { + this.windowClass = data + console.info('[AdvancedAPI] Succeeded in obtaining the top window. Unsubscribe keyboard change event.') + try { + if (callback) { + if (this.changeCallback.has(callback)) { + this.windowClass.off('keyboardHeightChange', this.changeCallback.get(callback)) + this.changeCallback.delete(callback) + } else { + console.info('[AdvancedAPI] Invalid callback.') + } + } else { + this.windowClass.off('keyboardHeightChange') + this.changeCallback.clear() + } + } catch (exception) { + console.error('[AdvancedAPI] Failed to unregister callback. Cause: ' + JSON.stringify(exception)) + } + }).catch((err) => { + console.error('[AdvancedAPI] Failed to obtain the top window. Cause: ' + JSON.stringify(err)) + }) + } catch (exception) { + console.error('[AdvancedAPI] Failed to obtain the top window. Cause: ' + JSON.stringify(exception)) + } + } +} diff --git a/ohos/AdvancedAPI_OHOS/src/advancedApi/module/ASLocation/index.js b/ohos/AdvancedAPI_OHOS/src/advancedApi/module/ASLocation/index.js new file mode 100644 index 0000000000..aebfa05093 --- /dev/null +++ b/ohos/AdvancedAPI_OHOS/src/advancedApi/module/ASLocation/index.js @@ -0,0 +1,189 @@ +import { AbilityBase, context } from '../../../base/bridge/abilityBase' +import abilityAccessCtrl from '@ohos.abilityAccessCtrl' +import geoLocationManager from '@ohos.geoLocationManager' +import mapCommon from '@hms.core.map.mapCommon' +import map from '@hms.core.map.map' +import wantAgent from '@ohos.app.ability.wantAgent' +import backgroundTaskManager from '@ohos.resourceschedule.backgroundTaskManager' +import { ErrorCode } from '../../../base/util/ErrorCode' +import Result from '../../../base/util/Result' + +export default class ASLocation { + constructor () { + this.locationChangeCallbacks = [] + this.locationChangeErrorCallback = (location, err) => {} + this.bothCallback = (location, err) => { + if (err) { + this.locationChangeErrorCallback({ + errMsg: err[2].arguments[0], errCode: err[2].arguments[1] + }) + } else { + for (let i = 0; i < this.locationChangeCallbacks.length; i++) { + this.locationChangeCallbacks[i].invokeAndKeepAlive(Result.success(location)) + } + } + } + } + + getLocation(params) { + console.debug('[AdvancedAPI] start ASLocation getLocation') + let permissions = ['ohos.permission.APPROXIMATELY_LOCATION'] + if (params?.isHighAccuracy) { + permissions = ['ohos.permission.APPROXIMATELY_LOCATION', 'ohos.permission.LOCATION'] + } + const atManager = abilityAccessCtrl.createAtManager() + return atManager.requestPermissionsFromUser(context, permissions).then((data) => { + const grantStatus = data.authResults + const dialogShownResults = data.dialogShownResults + const length = grantStatus.length + for (let i = 0; i < length; i++) { + if (grantStatus[i] !== 0 && data.permissions[i] === 'ohos.permission.APPROXIMATELY_LOCATION') { + return Promise.reject(['Permissions check failed,auth deny', ErrorCode.USER_REJECT, grantStatus[0], dialogShownResults[0]]) + } + } + + let requestInfo = { 'priority': 0x203, 'scenario': 0x300, 'maxAccuracy': 0 } + if (params?.highAccuracyExpireTime) { + requestInfo = { 'priority': 0x203, 'scenario': 0x300, 'maxAccuracy': 0, timeoutMs: params.highAccuracyExpireTime } + } + try { + return geoLocationManager.getCurrentLocation(requestInfo).then((result) => { + console.debug('[AdvancedAPI] current location: %s', JSON.stringify(result)) + if (params?.type === 'gcj02') { + const wgs84Position = { + latitude: result.latitude, + longitude: result.longitude + } + return map.convertCoordinate(mapCommon.CoordinateType.WGS84, mapCommon.CoordinateType.GCJ02, wgs84Position).then((gcj02Position) => { + result.latitude = gcj02Position.latitude + result.longitude = gcj02Position.longitude + return Promise.resolve(result) + }).catch((error) => { + console.debug('[AdvancedAPI] promise, convertCoordinate: error= %s', JSON.stringify(error)) + return Promise.reject([[error.message, ErrorCode.SERVICE_UNAVIALABLE]]) + }) + } else { + return Promise.resolve(result) + } + }) + .catch((error) => { + console.debug('[AdvancedAPI] promise, getCurrentLocation: error= %s', JSON.stringify(error)) + return Promise.reject([[error.message, ErrorCode.SERVICE_UNAVIALABLE]]) + }) + } catch (error) { + console.error('[AdvancedAPI] errCode:' + error.code + ',errMessage:' + error.message) + return Promise.reject([[error.message, ErrorCode.SERVICE_UNAVIALABLE]]) + } + }) + } + onLocationChange(callback) { + console.debug('[AdvancedAPI] start ASLocation onLocationChange') + this.locationChangeCallbacks.push(callback) + } + offLocationChange(callback) { + console.debug('[AdvancedAPI] start ASLocation offLocationChange') + if (callback) { + const index = this.locationChangeCallbacks.indexOf(callback) + if (index >= 0) { + this.locationChangeCallbacks.splice(index, 1) + } + } else { + this.locationChangeCallbacks = [] + } + } + onLocationChangeError(callback) { + console.debug('[AdvancedAPI] start ASLocation onLocationChangeError') + this.locationChangeErrorCallback = callback + } + offLocationChangeError() { + console.debug('[AdvancedAPI] start ASLocation offLocationChangeError') + this.locationChangeErrorCallback = (location, err) => {} + } + startLocationUpdate() { + console.debug('[AdvancedAPI] start ASLocation startLocationUpdate') + const permissions = ['ohos.permission.APPROXIMATELY_LOCATION', 'ohos.permission.LOCATION'] + const atManager = abilityAccessCtrl.createAtManager() + try { + return atManager.requestPermissionsFromUser(context, permissions).then((data) => { + const grantStatus = data.authResults + const length = grantStatus.length + for (let i = 0; i < length; i++) { + if (grantStatus[i] !== 0 && data.permissions[i] === 'ohos.permission.APPROXIMATELY_LOCATION') { + return Promise.reject([['Permissions check failed,auth deny', ErrorCode.USER_REJECT]]) + } + } + const requestInfo = { 'priority': 0x203, 'scenario': 0x300, 'timeInterval': 0, 'distanceInterval': 0, 'maxAccuracy': 0 } + try { + geoLocationManager.on('locationChange', requestInfo, this.bothCallback) + return Promise.resolve('SUCCESS') + } catch (error) { + return Promise.reject([[error.message, error.code]]) + } + }) + } catch (err) { + return Promise.reject([['startLocationUpdate failed', ErrorCode.COMMON_ERROR]]) + } + } + startLocationUpdateBackground() { + console.debug('[AdvancedAPI] start ASLocation startLocationUpdateBackground') + const permissions = ['ohos.permission.APPROXIMATELY_LOCATION', 'ohos.permission.LOCATION', 'ohos.permission.LOCATION_IN_BACKGROUND'] + const atManager = abilityAccessCtrl.createAtManager() + try { + return atManager.requestPermissionsFromUser(context, permissions).then((data) => { + const grantStatus = data.authResults + const length = grantStatus.length + for (let i = 0; i < length; i++) { + if (grantStatus[i] !== 0 + && (data.permissions[i] === 'ohos.permission.APPROXIMATELY_LOCATION' + || data.permissions[i] === 'ohos.permission.LOCATION_IN_BACKGROUND')) { + return Promise.reject([['Permissions check failed,auth deny', ErrorCode.USER_REJECT]]) + } + } + AbilityBase.getAbilityInfo().then(abilityInfo => { + const wantAgentInfo = { + wants: [ + { + bundleName: abilityInfo.bundleName, + abilityName: abilityInfo.name + } + ], + operationType: wantAgent.OperationType.START_ABILITY, + requestCode: 0, + wantAgentFlags: [wantAgent.WantAgentFlags.UPDATE_PRESENT_FLAG] + } + // use WantAgent to notify + wantAgent.getWantAgent(wantAgentInfo).then((wantAgentObj) => { + return backgroundTaskManager.startBackgroundRunning(context, backgroundTaskManager.BackgroundMode.LOCATION, wantAgentObj) + }).then(() => { + console.debug('[AdvancedAPI] start bg operation succeeded') + }).catch((err) => { + console.error('[AdvancedAPI] start bg operation failed Cause: ' + err) + }) + }) + const requestInfo = { 'priority': 0x203, 'scenario': 0x300, 'timeInterval': 0, 'distanceInterval': 0, 'maxAccuracy': 0 } + try { + geoLocationManager.on('locationChange', requestInfo, this.bothCallback) + return Promise.resolve('SUCCESS') + } catch (error) { + return Promise.reject([[error.message, error.code]]) + } + }) + } catch (err) { + return Promise.reject([['startLocationUpdateBackground failed', ErrorCode.COMMON_ERROR]]) + } + } + stopLocationUpdate(params) { + console.debug('[AdvancedAPI] start ASLocation stopLocationUpdate') + backgroundTaskManager.stopBackgroundRunning(context).then(() => { + console.debug('[AdvancedAPI] stop operation succeeded') + }).catch((err) => { + console.error('[AdvancedAPI] stop operation fail cause: ' + JSON.stringify(err)) + }) + try { + geoLocationManager.off('locationChange') + return Promise.resolve('SUCCESS') + } catch (err) { + return Promise.reject([['stopLocationUpdate failed', ErrorCode.COMMON_ERROR]]) + } + } +} diff --git a/ohos/AdvancedAPI_OHOS/src/advancedApi/module/ASPhone/index.js b/ohos/AdvancedAPI_OHOS/src/advancedApi/module/ASPhone/index.js new file mode 100644 index 0000000000..0c4254b682 --- /dev/null +++ b/ohos/AdvancedAPI_OHOS/src/advancedApi/module/ASPhone/index.js @@ -0,0 +1,13 @@ +import call from '@ohos.telephony.call' +import { ErrorCode } from '../../../base/util/ErrorCode' +export default class ASPhone { + makePhoneCall(number) { + if (!number || !number.phoneNumber || (typeof number.phoneNumber !== 'string') || number === '') { + return new Promise((resolve, reject) => { + reject(['param is invalid.', ErrorCode.PARAMETER_ERROR]) + }) + } + const promise = call.makeCall(number.phoneNumber) + return promise + } +} diff --git a/ohos/AdvancedAPI_OHOS/src/advancedApi/module/ASRequest/index.js b/ohos/AdvancedAPI_OHOS/src/advancedApi/module/ASRequest/index.js new file mode 100644 index 0000000000..7b2724e690 --- /dev/null +++ b/ohos/AdvancedAPI_OHOS/src/advancedApi/module/ASRequest/index.js @@ -0,0 +1,739 @@ +/** + * Copyright (c) Huawei Technologies Co., Ltd. 2023-2023. All rights reserved. + * Description: advanced request api + * Create: 04/01/2023 + * Notes: Permissions: ohos.permission.INTERNET + */ +import http from '@ohos.net.http' +import request from '@ohos.request' +import { pathToCache, switchInternalToHapSandBox } from '../../util' +import { arrayBufferToBase64 } from '../../as/base/arrayBuffer2Base64' + +// Http errCode +const errMsgMap = new Map([ + [401, 'Parameter error'], + [201, 'Permission denied'], + [2300003, 'URL using bad/illegal format or missing URL'], + [2300006, 'Could not resolve host name'], + [2300007, 'Couldn not connect to server'], + [2300009, 'Access denied to remote resource'], + [2300023, 'Failed writing received data to disk/application'], + [2300025, 'Upload failed'], + [2300026, 'Failed to open/read local data from file/application'], + [2300028, 'Timeout was reached'], + [2300073, 'Remote file already exists'], + [2300078, 'Remote file not found'], + [2300999, 'Unknown Other Error'] +]) + +// AS API class +export default class ASRequest { + /** + * make a network request + * Required + * @object params url {String}: server address + * Optional + * @object params data {Object|String|ArrayBuffer}: request params + * @object params header {Object}: HTTP request Header + * @object params method {String}: support OPTIONS, GET, HEAD, POST, PUT, DELETE, TRACE, CONNECT, default is GET + * @object params timeout {Number}: timeout time, default is 60000 + * @object params dataType {String}: data type, default is json (ohos not support) + * @object params responseType {String}: response data type, text or arraybuffer, default is text + * @object params sslVerify {Boolean}: verify ssl certificate, default is true (ohos not support) + * @object params withCredentials {Boolean}: cross-domain requests with credentials, default is false (ohos not support) + * @object params firstIpv4 {Boolean}: use ipv4 first when DNS resolution, default is false (ohos not support) + * @object params enableHttp2 {Boolean}: enable http2, default is false (ohos not support) + * @object params enableQuic {Boolean}: enable quic, default is false (ohos not support) + * @object params enableCache {Boolean}: enable cache, default is false + * @object params enableHttpDNS {Boolean}: enable HttpDNS service with httpDNSServiceId, default is false (ohos not support) + * @object params httpDNSServiceId {String}: httpDNS service provider ID (ohos not support) + * @object params enableChunked {Boolean}: enable transfer-encoding chunked, default is false (ohos not support) + * @object params forceCellularNetwork {Boolean}: Use mobile network under wifi, default is false (ohos not support) + * @object params enableCookie {Boolean}: can edit cookies in headers if enabled, default is false (ohos not support) + * @object params defer {Boolean}: data type, default is false (ohos not support) + * @object params cloudCache {Object|Boolean}: enable cloud acceleration, default is false (ohos not support) + * @object params success {Function}: success callback + * @object params fail {Function}: fail callback + * @object params complete {Function}: complete callback + * Callback + * @success params data {Object|String|ArrayBuffer}: data returned by server + * @success params statusCode {Number}: status code returned by server + * @success params header {Object}: HTTP Response Header returned by server + * @success params cookies {Array.}: cookies returned by server + * + * @returns {requestTask|Promise} : return requestTask if has callback otherwise return promise (handled in interface class) + */ + request(object) { + console.debug('[AdvancedAPI] ASRequest request') + return new RequestTask(object) + } + + /** + * request to upload files + * Required + * @object params url {String}: server address + * Required Optional 1 + * @object params files {Array}: upload files list, file object include name{String}, file{File}, uri{String} + * Required Optional 2 + * @object params filePath {String}: upload file path + * @object params name {String}: upload file key + * Optional + * @object params fileType {String}: file type, image/video/audio (ohos not support) + * @object params file {File}: upload file object (ohos not support) + * @object params header {Object}: HTTP request Header + * @object params timeout {Number}: timeout time (ohos not support) + * @object params formData {Object}: extra form data + * @object params success {Function}: success callback + * @object params fail {Function}: fail callback + * @object params complete {Function}: complete callback + * Callback + * @success params data {String}: data returned by server (ohos not support) + * @success params statusCode {Number}: status code returned by server, 200 for HTTP OK (ohos not support) + * + * @returns {uploadTask|Promise} : return uploadTask if has callback otherwise return promise (handled in interface class) + * + * Note + * ohos only support internal:// uri + */ + uploadFile(object) { + console.debug('[AdvancedAPI] ASRequest uploadFile : %s', JSON.stringify(object)) + return new UploadTask(object) + } + + /** + * request to download files + * Required + * @object params url {String}: file server address + * Optional + * @object params header {Object}: HTTP request Header + * @object params timeout {Number}: timeout time (ohos not support) + * @object params success {Function}: success callback + * @object params fail {Function}: fail callback + * @object params complete {Function}: complete callback + * @object params filePath {String}: specialized the local storage path (ohos required) + * Callback + * @success params tempFilePath {String}: temp file storage path + * @success params statusCode {Number}: status code returned by server, 200 for HTTP OK + * + * @returns {downloadTask|Promise} : return downloadTask if has callback otherwise return promise (handled in interface class) + */ + downloadFile(object) { + console.debug('[AdvancedAPI] ASRequest downloadFile %s', JSON.stringify(object)) + return new DownloadTask(object) + } +} + +// RequestTask class +class RequestTask { + /** + * constructor function, create http request + * Required + * @object params url {String}: server address + * Optional + * @object params data {Object|String|ArrayBuffer}: request params + * @object params header {Object}: HTTP request Header + * @object params method {String}: support OPTIONS, GET, HEAD, POST, PUT, DELETE, TRACE, CONNECT, default is GET + * @object params timeout {Number}: timeout time, default is 60000 + * @object params responseType {String}: response data type, text or arraybuffer, default is text + * @object params enableCache {Boolean}: enable cache, default is false + * @object params success {Function}: success callback + * @object params fail {Function}: fail callback + * @object params complete {Function}: complete callback + * Callback + * @success params data {Object|String|ArrayBuffer}: data returned by server + * @success params statusCode {Number}: status code returned by server, 200 for HTTP OK + * @success params header {Object}: HTTP Response Header returned by server + * @success params cookies {Array.}: cookies returned by server + */ + constructor(object) { + const { url, header, method = 'GET', timeout, responseType, enableCache } = object || {} + let { data } = object || {} + const { success, fail, complete } = object || {} + + this.abortFlag = false + this.fail = fail + this.complete = complete + this.httpRequest = http.createHttp() + this.headersCallback = new Map() + + if (!object) { + console.error('[AdvancedAPI] request error: params illegal') + return + } + + let isFormUrlEncoded = false + for (const key in header) { + if (key.toLowerCase() === 'content-type') { + if (header[key].toLowerCase().includes('application/x-www-form-urlencoded')) { + isFormUrlEncoded = true + } + break + } + } + + // data为Object类型时,属性的值类型如果是number, request请求时信息会丢失. 故将data转成string类型进行规避 + if (data && (isFormUrlEncoded || ['GET', 'OPTIONS', 'DELETE', 'TRACE', 'CONNECT'].includes(method))) { + const dataArray = [] + for (const key in data) { + dataArray.push(encodeURIComponent(key) + '=' + encodeURIComponent(data[key])) + } + data = dataArray.join('&') + } + // header的属性的值类型如果是number, request请求时信息会丢失. 故将各个属性转成string类型 + if (header) { + for (const key in header) { + header[key] = `${header[key]}` + } + } + + const httpRequestOptions = { + method: method, + extraData: data || {}, + header: header, + expectDataType: (responseType && responseType === 'arraybuffer') ? http.HttpDataType.ARRAY_BUFFER : http.HttpDataType.STRING, + usingCache: enableCache || false + } + let isTimeout = false + const timer = setTimeout(() => { + console.error('[AdvancedAPI] request error: Timeout was reached') + isTimeout = true + if (fail && !this.abortFlag) { + const res = { errMsg: 'Timeout was reached' } + this.result = res + fail(res) + } + if (complete && !this.abortFlag) { + complete(this.result) + } + if (this.httpRequest) { + this.httpRequest.destroy() + this.httpRequest = undefined + } + }, timeout || 60000) + this.httpRequest.request((typeof url === 'string') ? url : '', httpRequestOptions) + .then((data) => { + clearTimeout(timer) + console.debug('[AdvancedAPI] request url %s success', url) + if (success && !this.abortFlag) { + let result = data.result + let isArrayBuffer = false + const { responseType } = object || {} + // 返回数据类型dataType不为json时需要考虑将ArrayBuffer数据先转换为base64字符串 + if (responseType && responseType !== 'json') { + if (Object.prototype.toString.call(result) === '[object ArrayBuffer]') { + // expectDataType响应数据类型只有ARRAY_BUFFER和STRING两种 + result = arrayBufferToBase64(result) + isArrayBuffer = true + } + } else if (typeof data.result === 'string') { + // 返回数据类型dataType为json时,尝试将字符串转换为JSON对象,若无法转换则仍返回字符串 + try { + result = JSON.parse(result) + } catch (err) { } + } + const res = { + isArrayBuffer: false, + data: result, + statusCode: data.responseCode, + header: data.header, + cookies: typeof data.cookies === 'string' ? (data.cookies ? [data.cookies] : []) : data.cookies, + errMsg: 'request:ok' + } + if (isArrayBuffer) { + res.isArrayBuffer = true + } + this.result = res + success(res) + } + }) + .catch((err) => { + // 若超出request的默认超时时间,也会走超时。connectTimeout和readTimeout默认均为60000ms。 + clearTimeout(timer) + if (!isTimeout) { + console.error('[AdvancedAPI] request error: ' + JSON.stringify(err)) + if (fail && !this.abortFlag) { + const res = { errMsg: errMsgMap.has(err.code) ? errMsgMap.get(err.code) : 'Unknown Error' } + this.result = res + fail(res) + } + } + }) + .finally(() => { + if (!isTimeout) { + if (complete && !this.abortFlag) { + complete(this.result) + } + if (this.httpRequest) { + this.httpRequest.destroy() + this.httpRequest = undefined + } + } + }) + } + + /** + * interrupt request task + */ + abort() { + console.debug('[AdvancedAPI] request abort') + this.abortFlag = true + if (this.httpRequest) { + this.httpRequest.destroy() + this.httpRequest = undefined + this.res = { errMsg: 'request:fail abort' } + this.fail && this.fail(this.res) + this.complete && this.complete(this.res) + } + } + + /** + * subscribe HTTP Response Header event + * @callback params header {Object}: HTTP Response Header + */ + onHeadersReceived(callback) { + const taskCallback = (header) => { + !this.abortFlag && callback({ header }) + } + if (!callback) { + console.error('[AdvancedAPI] Invalid, callback is null') + return + } + if (!this.headersCallback.has(callback)) { + this.headersCallback.set(callback, taskCallback) + if (this.httpRequest) { + this.httpRequest.on('headersReceive', taskCallback) + } + } + } + + /** + * unsubscribe HTTP Response Header event + * remove all if callback is null, otherwise remove the specialized callback + */ + offHeadersReceived(callback) { + if (!callback) { + this.headersCallback.clear() + if (this.httpRequest) { + this.httpRequest.off('headersReceive') + } + } else if (this.headersCallback.has(callback)) { + if (this.httpRequest) { + this.httpRequest.off('headersReceive', this.headersCallback.get(callback)) + } + this.headersCallback.delete(callback) + } else { + console.debug('[AdvancedAPI] offHeadersReceived callback invalid') + } + } +} + +// UploadTask class +class UploadTask { + /** + * constructor function, create download request + * Required + * @object params url {String}: server address + * Required Optional 1 + * @object params files {Array}: upload files object list, file object include name{String}, file{File}, uri{String} + * Required Optional 2 + * @object params filePath {String}: upload file path + * @object params name {String}: upload file key + * Optional + * @object params header {Object}: HTTP request Header + * @object params formData {Object}: extra form data + * @object params success {Function}: success callback + * @object params fail {Function}: fail callback + * @object params complete {Function}: complete callback + * Callback + * @success params data {String}: data returned by server + * @success params statusCode {Number}: status code returned by server, 200 for HTTP OK + */ + constructor(object) { + const { url, files, filePath, name, header, formData } = object || {} + const { success, fail, complete } = object || {} + const filePath1 = filePath.startsWith('internal://cache/') ? filePath : pathToCache(filePath) + + this.progressCallback = new Map() + this.headersCallback = new Map() + + const uploadFiles = [] + if (files) { + files.forEach(function (file) { + if (typeof file.uri === 'string') { + const filename = file.uri.substring(file.uri.lastIndexOf('/') + 1) + const type = file.uri.substring(file.uri.lastIndexOf('.') + 1) + uploadFiles.push({ filename: filename, name: file.name, uri: file.uri, type: type }) + } + }) + } else if (typeof filePath1 === 'string') { + const filename = filePath1.substring(filePath1.lastIndexOf('/') + 1) + const type = filePath1.substring(filePath1.lastIndexOf('.') + 1) + uploadFiles.push({ filename: filename, name: name, uri: filePath1, type: type }) + } + const formDataArray = [] + for (const [key, value] of Object.entries(formData || {})) { + formDataArray.push({ + name: key, + value: typeof value === 'string' ? value : JSON.stringify(value), + }) + } + const uploadConfig = { + url: url, + header: header || {}, + method: 'POST', + files: uploadFiles, + data: formDataArray, + } + this.successHandle = (res) => { + success && success(res) + complete && complete(res) + } + this.failHandle = (res) => { + fail && fail(res) + complete && complete(res) + } + try { + console.debug('[AdvancedAPI] request upload') + request.uploadFile(globalThis.abilityContext, uploadConfig) + .then((data) => { + this.uploadTask = data + if (this.abortFlag) { + this.abortFlag = false + this.uploadTask.delete(() => { + this.res = { errMsg: 'uploadFile:fail abort' } + this.failHandle(this.res) + }) + } + if (this.progressFlag) { + this.progressFlag = false + for (const taskCallback of this.progressCallback.values()) { + this.uploadTask.on('progress', taskCallback) + } + } + if (this.headersFlag) { + this.headersFlag = false + for (const callback of this.headersCallback.values()) { + this.uploadTask.on('headerReceive', callback) + } + } + this.uploadTask.on('headerReceive', this.headersReceivedHandle.bind(this)) + this.uploadTask.on('complete', () => { + console.debug('[AdvancedAPI] upload success') + this.res = { + data: this.receivedData?.body || {}, + header: this.receivedData?.headers || {}, + cookies: [], + statusCode: 200, errMsg: + 'uploadFile:ok' + } + this.successHandle(this.res) + }) + this.uploadTask.on('fail', () => { + console.debug('[AdvancedAPI] upload fail') + this.res = { errMsg: 'uploadFile:fail' } + this.failHandle(this.res) + }) + }) + .catch((err) => { + console.error('[AdvancedAPI] upload request error: ' + err.message) + this.res = { errMsg: `uploadFile:fail ${err.message}` } + this.failHandle(this.res) + }) + } catch (err) { + console.error('[AdvancedAPI] upload request err.code : ' + err.code + ', err.message : ' + err.message) + this.res = { errMsg: `uploaddFile:fail ${err.message}` } + this.failHandle(this.res) + } + } + + /** + * interrupt upload task + */ + abort() { + this.res = { errMsg: 'uploadFile:fail abort' } + if (this.uploadTask) { + this.uploadTask.delete(() => { + this.failHandle(this.res) + }) + } else { + this.abortFlag = true + } + } + + /** + * subscribe upload process event + * @callback params progress {Number}: upload process percent + * @callback params totalBytesSent {Number}: upload Bytes + * @callback params totalBytesExpectedToSend {Number}: total Bytes + */ + onProgressUpdate(callback) { + function taskCallback(uploadedSize, totalSize) { + callback({ progress: Math.ceil(100 * uploadedSize / totalSize), totalBytesSent: uploadedSize, totalBytesExpectedToSend: totalSize }) + } + if (!callback) { + console.error('[AdvancedAPI] Invalid, callback is null') + return + } + if (!this.progressCallback.has(callback)) { + this.progressCallback.set(callback, taskCallback) + if (this.uploadTask) { + this.uploadTask.on('progress', taskCallback) + } else { + this.progressFlag = true + } + } + } + + /** + * unsubscribe upload process event + * remove all if callback is null, otherwise remove the specialized callback + */ + offProgressUpdate(callback) { + if (!callback) { + this.progressCallback.clear() + // if task is not ready, on is not set too + if (this.uploadTask) { + this.uploadTask.off('progress') + } + } else if (this.progressCallback.has(callback)) { + if (this.uploadTask) { + this.uploadTask.off('progress', this.progressCallback.get(callback)) + } + this.progressCallback.delete(callback) + } else { + console.debug('[AdvancedAPI] offProgressUpdate callback invalid') + } + } + + /** + * subscribe HTTP Response Header event + */ + headersReceivedHandle(info) { + this.receivedData = info + } + + /** + * subscribe HTTP Response Header event + * @callback params header {Object}: HTTP Response Header + */ + onHeadersReceived(callback) { + const taskCallback = (info) => { + !this.abortFlag && callback({ header: info.headers || {}}) + } + if (!callback) { + console.error('[AdvancedAPI] Invalid, callback is null') + return + } + if (!this.headersCallback.has(callback)) { + this.headersCallback.set(callback, taskCallback) + if (this.uploadTask) { + this.uploadTask.on('headerReceive', taskCallback) + } else { + this.headersFlag = true + } + } + } + + /** + * unsubscribe HTTP Response Header event + * remove all if callback is null, otherwise remove the specialized callback + */ + offHeadersReceived(callback) { + if (!callback) { + this.headersCallback.clear() + if (this.uploadTask) { + this.uploadTask.off('headerReceive') + this.uploadTask.on('headerReceive', this.headersReceivedHandle.bind(this)) + } + } else if (this.headersCallback.has(callback)) { + if (this.uploadTask) { + this.uploadTask.off('headerReceive', this.headersCallback.get(callback)) + } + this.headersCallback.delete(callback) + } else { + console.debug('[AdvancedAPI] offHeadersReceived callback invalid') + } + } +} + +// DownloadTask class +class DownloadTask { + /** + * constructor function, create download request + * Required + * @object params url {String}: file server address + * @object params filePath {String}: specialized the local storage path, if null, use default cache dir + * Optional + * @object params header {Object}: HTTP request Header + * @object params success {Function}: success callback + * @object params fail {Function}: fail callback + * @object params complete {Function}: complete callback + * Callback + * @success params tempFilePath {String}: temp file storage path + * @success params statusCode {Number}: status code returned by server, 200 for HTTP OK + */ + constructor(object) { + const { url, header, filePath } = object || {} + const { success, fail, complete } = object || {} + this.progressCallback = new Map() + + if (typeof url === 'string') { + const timestamp = new Date().getTime() + this.filename = 'Download_' + timestamp + '_' + url.substring(url.lastIndexOf('/') + 1).replace(/[^a-zA-Z0-9.]/, '').slice(-16) + } + + const interalFilePath = filePath || `internal://cache/${this.filename}` + const sanBoxFilePath = switchInternalToHapSandBox(interalFilePath) + const downloadConfig = { + url: this.isEncodeUri(url) ? url : encodeURI(url), + header: header || {}, // undefined error + filePath: sanBoxFilePath, + } + + this.successHandle = (res) => { + success && success(res) + complete && complete(res) + } + this.failHandle = (res) => { + fail && fail(res) + complete && complete(res) + } + try { + console.debug('[AdvancedAPI] request download') + request.downloadFile(globalThis.abilityContext, downloadConfig) + .then((data) => { + this.downloadTask = data + if (this.abortFlag) { + this.abortFlag = false + this.downloadTask.delete(() => { + console.debug('[AdvancedAPI] download fail') + this.res = { errMsg: 'downloadFile:fail abort' } + this.failHandle(this.res) + }) + } + if (this.progressFlag) { + this.progressFlag = false + for (const taskCallback of this.progressCallback.values()) { + this.downloadTask.on('progress', taskCallback) + } + } + this.downloadTask.on('complete', () => { + console.debug('[AdvancedAPI] download success') + this.res = { tempFilePath: interalFilePath, statusCode: 200, errMsg: 'downloadFile:ok' } + filePath && Object.assign(this.res, { filePath }) + this.downloadTask.getTaskInfo().then((info) => { + console.debug('[AdvancedAPI] download info: %s', JSON.stringify(info)) + info.downloadTotalBytes && Object.assign(this.res, { dataLength: info.downloadTotalBytes }) + }).catch((err) => { + console.error('[AdvancedAPI] download request get task info error: ' + err.message) + }).finally(() => { + this.successHandle(this.res) + }) + }) + this.downloadTask.on('fail', () => { + console.debug('[AdvancedAPI] download fail') + this.res = { errMsg: 'downloadFile:fail' } + this.failHandle(this.res) + }) + }) + .catch((err) => { + console.error('[AdvancedAPI] download request error: ' + err.message) + this.res = { errMsg: `downloadFile:fail ${err.message}` } + this.failHandle(this.res) + }) + } catch (err) { + console.error('[AdvancedAPI] download request err.code : ' + err.code + ', err.message : ' + err.message) + this.res = { errMsg: `downloadFile:fail ${err.message}` } + this.failHandle(this.res) + } + } + + /** + * interrupt download task + */ + abort() { + if (this.downloadTask) { + this.downloadTask.delete(() => { + console.debug('[AdvancedAPI] download fail') + this.res = { errMsg: 'downloadFile:fail abort' } + this.failHandle(this.res) + }) + } else { + this.abortFlag = true + } + } + + /** + * subscribe download process event + * @callback params progress {Number}: download process percent + * @callback params totalBytesWritten {Number}: download Bytes + * @callback params totalBytesExpectedToWrite {Number}: total Bytes + */ + onProgressUpdate(callback) { + function taskCallback(receivedSize, totalSize) { + callback({ progress: Math.ceil(100 * receivedSize / totalSize), totalBytesWritten: receivedSize, totalBytesExpectedToWrite: totalSize }) + } + if (!callback) { + console.error('[AdvancedAPI] Invalid, callback is null') + return + } + if (!this.progressCallback.has(callback)) { + this.progressCallback.set(callback, taskCallback) + if (this.downloadTask) { + this.downloadTask.on('progress', taskCallback) + } else { + this.progressFlag = true + } + } + } + + /** + * unsubscribe download process event + * remove all if callback is null, otherwise remove the specialized callback + */ + offProgressUpdate(callback) { + if (!callback) { + this.progressCallback.clear() + // if task is not ready, on is not set too + if (this.downloadTask) { + this.downloadTask.off('progress') + } + } else if (this.progressCallback.has(callback)) { + if (this.downloadTask) { + this.downloadTask.off('progress', this.progressCallback.get(callback)) + this.progressCallback.delete(callback) + } + } else { + console.debug('[AdvancedAPI] offProgressUpdate callback invalid') + } + } + + /** + * subscribe HTTP Response Header event + * @callback params header {Object}: HTTP Response Header + * ohos not support + */ + onHeadersReceived(callback) { + console.debug('[AdvancedAPI] onHeadersReceived not support') + } + + /** + * unsubscribe HTTP Response Header event + * remove all if callback is null, otherwise remove the specialized callback + * ohos not support + */ + offHeadersReceived(callback) { + console.debug('[AdvancedAPI] offHeadersReceived not support') + } + + /** + * check whether a string contains only valid characters of encodeUri + */ + isEncodeUri(uri) { + const validRep = /^[a-zA-Z0-9-_.!~*'();/?:@&=+$,#]+$/ + if (!uri) { + return true + } + return validRep.test(uri) + } +} diff --git a/ohos/AdvancedAPI_OHOS/src/advancedApi/module/ASRouter/index.js b/ohos/AdvancedAPI_OHOS/src/advancedApi/module/ASRouter/index.js new file mode 100644 index 0000000000..bc09bcf49f --- /dev/null +++ b/ohos/AdvancedAPI_OHOS/src/advancedApi/module/ASRouter/index.js @@ -0,0 +1,129 @@ +import router from '@ohos.router' +import { ErrorCode } from '../../../base/util/ErrorCode' + +export default class ASRouter { + /** + * 保留当前页面,跳转到应用内的某个页面 + * @param {string} url - 需要跳转的应用内非 tabBar 的页面的路径 + * @param {string} animationType - 窗口显示的动画效果(不支持) + * @param {number} animationDuration - 窗口动画持续时间,单位为 ms(不支持) + * @param {object} events - 页面间通信接口,用于监听被打开页面发送到当前页面的数据。(不支持) + * @param {function} success + * @param {function} fail + * @param {function} complete + */ + navigateTo (params) { + return new Promise((resolve, reject) => { + if (typeof params.url !== 'string') { + reject(['param url', ErrorCode.PARAMETER_ERROR]) + return + } + const { url, urlParams } = getUrlParams(params.url) + console.debug('[AdvancedAPI] navigateTo urlParams = %s', JSON.stringify(urlParams)) + router.pushUrl({ + url: url, + params: urlParams + }).then(() => { + resolve() + }).catch(err => { + console.error(`[AdvancedAPI] pushUrl failed, code is ${err.code}, message is ${err.message}`) + reject([err.message, err.code]) + }) + }) + } + + /** + * 关闭当前页面,跳转到应用内的某个页面 + * @param {string} url - 需要跳转的应用内非 tabBar 的页面的路径 + * @param {function} success + * @param {function} fail + * @param {function} complete + */ + redirectTo (params) { + return new Promise((resolve, reject) => { + if (typeof params.url !== 'string') { + reject(['param url', ErrorCode.PARAMETER_ERROR]) + return + } + const { url, urlParams } = getUrlParams(params.url) + console.debug('[AdvancedAPI] redirectTo urlParams = ' + JSON.stringify(urlParams)) + router.replaceUrl({ + url, + params: urlParams + }).then(() => { + resolve() + }).catch(err => { + console.error(`[AdvancedAPI] replaceUrl failed, code is ${err.code}, message is ${err.message}`) + reject([err.message, err.code]) + }) + }) + } + + /** + * 跳转到 tabBar 页面,并关闭其他所有非 tabBar 页面。 + * 当时无法实现:需要通过api来控制tabs组件的index + * @param {string} url - 需要跳转的 tabBar 页面的路径 + * @param {function} success + * @param {function} fail + * @param {function} complete + */ + switchTab (params) { + return new Promise(async (resolve, reject) => { + reject('[AdvancedAPI] switchTab do not support') + }) + } + + /** + * 关闭当前页面,返回上一页面或多级页面。 + * @param {number} delta - 返回的页面数,如果 delta 大于现有页面数,则返回到首页。 + * @param {string} animationType - 窗口关闭的动画效果 + * @param {number} animationDuration - 窗口关闭动画的持续时间,单位为 ms + * @param {function} success + * @param {function} fail + * @param {function} complete + */ + navigateBack (params) { + return new Promise((resolve, reject) => { + let { delta = 1 } = params + if (delta === null) { + delta = 1 + } + if (typeof delta !== 'number') { + reject(['parameter delta', ErrorCode.PARAMETER_ERROR]) + return + } + const pageLengths = Number(router.getLength()) + if (delta > pageLengths) { + delta = pageLengths - 1 + } + try { + // 此处应该是要获取到页面栈所有对象的路径,然后调用鸿蒙的back接口指定返回页面的路劲 + // 但是鸿蒙没有提供获取所有页面路径的接口 + for (let i = 0; i < delta; i++) { + router.back() + } + resolve() + } catch (err) { + reject([err.data, err.code]) + } + }) + } +} + +/** + * 解析url=pages/Index?id=1&name=uniapp + * @param {string} url + * @return {object} object + */ +function getUrlParams (url = '') { + const urlParams = {} + const urlArr = url.split('?') + url = urlArr[0] + let tempParams = urlArr[1] || '' + tempParams = tempParams.split('&') + tempParams.forEach(item => { + const itemArr = item.split('=') + urlParams[itemArr[0]] = itemArr[1] + }) + return { url, urlParams } +} diff --git a/ohos/AdvancedAPI_OHOS/src/advancedApi/module/ASScan/index.js b/ohos/AdvancedAPI_OHOS/src/advancedApi/module/ASScan/index.js new file mode 100644 index 0000000000..557e0acf77 --- /dev/null +++ b/ohos/AdvancedAPI_OHOS/src/advancedApi/module/ASScan/index.js @@ -0,0 +1,112 @@ +import scanCore from '@hms.core.scan.scanCore' +import scanBarcode from '@hms.core.scan.scanBarcode' +import { ErrorCode } from '../../../base/util/ErrorCode' +import { isBoolean } from '../../../base/util/checkDataType' +import { Base64 } from 'js-base64' + +const SCAN_TYPE_AS_TO_HM = { + 'barCode': scanCore?.ScanType.ONE_D_CODE, + 'qrCode': scanCore?.ScanType.TWO_D_CODE, + 'datamatrix': scanCore?.ScanType.DATAMATRIX_CODE, + 'pdf417': scanCore?.ScanType.PDF417_CODE +} + +export default class ASScan { + scanCode(params = {}) { + return new Promise((resolve, reject) => { + const { onlyFromCamera = false, hideAlbum = false, scanType = [] } = params + const scanTypes = [] + for (let i = 0; i < scanType.length; i++) { + if (SCAN_TYPE_AS_TO_HM[scanType[i]]) { + scanTypes.push(SCAN_TYPE_AS_TO_HM[scanType[i]]) + } else { + reject(['Parameter scanType invalid!', ErrorCode.PARAMETER_ERROR]) + return + } + } + if (!isBoolean(onlyFromCamera)) { + reject(['Parameter onlyFromCamera invalid!', ErrorCode.PARAMETER_ERROR]) + return + } + if (!isBoolean(hideAlbum)) { + reject(['Parameter hideAlbum invalid!', ErrorCode.PARAMETER_ERROR]) + return + } + if (scanTypes.length === 0) { + scanTypes.push(scanCore.ScanType.ALL) + } + const options = { scanTypes, enableMultiMode: false, enableAlbum: (!onlyFromCamera && !hideAlbum) } + try { + scanBarcode.startScan(options).then((result) => { + resolve({ + result: result.originalValue, + scanType: this.scanTypeHmToAs(result.scanType), + rawData: Base64.btoa(result.originalValue), + charSet: 'utf-8' + }) + }).catch((failResult) => { + reject(['scanCode fail!', ErrorCode.COMMON_ERROR]) + }) + } catch (error) { + reject(['scanCode fail!', ErrorCode.COMMON_ERROR]) + } + }) + } + + scanTypeHmToAs(type) { + let asType = 'UNKNOWN' + switch (type) { + case scanCore.ScanType.DATAMATRIX_CODE: + asType = 'DATA_MATRIX' + break + case scanCore.ScanType.PDF417_CODE: + asType = 'PDF_417' + break + case scanCore.ScanType.AZTEC_CODE: + asType = 'AZTEC' + break + case scanCore.ScanType.CODABAR_CODE: + asType = 'CODABAR' + break + case scanCore.ScanType.CODE39_CODE: + asType = 'CODE_39' + break + case scanCore.ScanType.CODE93_CODE: + asType = 'CODE_93' + break + case scanCore.ScanType.CODE128_CODE: + asType = 'CODE_128' + break + case scanCore.ScanType.EAN8_CODE: + asType = 'EAN_8' + break + case scanCore.ScanType.EAN13_CODE: + asType = 'EAN_13' + break + case scanCore.ScanType.ITF14_CODE: + asType = 'ITF' + break + case scanCore.ScanType.QR_CODE: + asType = 'QR_CODE' + break + case scanCore.ScanType.UPC_A_CODE: + asType = 'UPC_A' + break + case scanCore.ScanType.UPC_E_CODE: + asType = 'UPC_E' + break + case scanCore.ScanType.MULTIFUNCTIONAL_CODE: + asType = 'MULTIFUNCTIONAL' + break + case scanCore.ScanType.ONE_D_CODE: + asType = 'CODABAR' + break + case scanCore.ScanType.TWO_D_CODE: + asType = 'QR_CODE' + break + default: + break + } + return asType + } +} diff --git a/ohos/AdvancedAPI_OHOS/src/advancedApi/module/ASVibrator/index.js b/ohos/AdvancedAPI_OHOS/src/advancedApi/module/ASVibrator/index.js new file mode 100644 index 0000000000..e975fccc99 --- /dev/null +++ b/ohos/AdvancedAPI_OHOS/src/advancedApi/module/ASVibrator/index.js @@ -0,0 +1,82 @@ +/** + * Copyright (c) Huawei Technologies Co., Ltd. 2022-2022. All rights reserved. + * Description: default description + * Author: weisufang + * Create: 04/12/2023 + * 需要权限: ohos.permission.VIBRATE + */ + +import vibrator from '@ohos.vibrator' + +export default class ASVibrator { + /** + * 使手机发生振动。 + * @param {function} success - 接口调用成功的回调函数 + * @param {function} fail - 接口调用失败的回调函数 + * @param {function} complete - 接口调用结束的回调函数(调用成功、失败都会执行) + */ + vibrate () { + return new Promise((resolve, reject) => { + this.triggerVibrate({ duration: 200 }).then(data => { + resolve(data) + }).catch(err => { + reject([err.data, err.code]) + }) + }) + } + + /** + * 使手机发生较长时间的振动(400ms) + * @param {function} success - 接口调用成功的回调函数 + * @param {function} fail - 接口调用失败的回调函数 + * @param {function} complete - 接口调用结束的回调函数(调用成功、失败都会执行) + */ + vibrateLong () { + return new Promise((resolve, reject) => { + this.triggerVibrate({ duration: 400 }).then(data => { + resolve(data) + }).catch(err => { + reject([err.data, err.code]) + }) + }) + } + + /** + * 使手机发生较短时间的振动(15ms) + * @param {function} success - 接口调用成功的回调函数 + * @param {function} fail - 接口调用失败的回调函数 + * @param {function} complete - 接口调用结束的回调函数(调用成功、失败都会执行) + */ + vibrateShort () { + return new Promise((resolve, reject) => { + this.triggerVibrate({ duration: 15 }).then(data => { + resolve(data) + }).catch(err => { + reject([err.data, err.code]) + }) + }) + } + + triggerVibrate (params) { + return new Promise((resolve, reject) => { + const effect = { + type: 'time', + duration: params.duration + } + const attribute = { + id: 0, + usage: 'alarm' + } + vibrator.startVibration(effect, attribute).then(data => { + console.debug('[AdvancedAPI] startVibration success') + resolve(data) + }, (err) => { + console.error(`[AdvancedAPI] startVibration fail err = ${JSON.stringify(err)}`) + reject(err) + }).catch((err) => { + console.error(`[AdvancedAPI] startVibration fail err = ${JSON.stringify(err)}`) + reject(err) + }) + }) + } +} diff --git a/ohos/AdvancedAPI_OHOS/src/advancedApi/module/ASVideo/index.js b/ohos/AdvancedAPI_OHOS/src/advancedApi/module/ASVideo/index.js new file mode 100644 index 0000000000..79048bdfaa --- /dev/null +++ b/ohos/AdvancedAPI_OHOS/src/advancedApi/module/ASVideo/index.js @@ -0,0 +1,165 @@ +import { + getFileAssetFromUri, + isFileUri, + isSandboxPath, + getFdFromUriOrSandBoxPath, + switchInternalToHapSandBox, + saveMedia +} from '../../util/index' +import fs from '@ohos.file.fs' +import { ErrorCode } from '../../../base/util/ErrorCode' +// import { MediaLibraryBase } from '../../../base/bridge/mediaLibraryBase' +import { FileioBase } from '../../../base/bridge/fileioBase' +import photoAccessHelper from '@ohos.file.photoAccessHelper' +// import { context } from '../../../base/bridge/abilityBase' +import fileUri from '@ohos.file.fileuri' + +// const ORI = { +// 0: 'left', +// 90: 'up', +// 180: 'right', +// 270: 'down', +// } + +export default class ASViedo { + getVideoInfo(params) { + return new Promise(async (resolve, reject) => { + return reject(['getVideoInfo is not support!']) + // const permission = await MediaLibraryBase.getPermissions() + // if (permission.perNum === -1) { + // return reject(['permission fail', ErrorCode.USER_REJECT, permission.perNum, permission.dialogShownResults]) + // } + // try { + // let uri = params.src + // if (isFileUri(uri)) { + // const asset = await getFileAssetFromUri(uri) + // const orientation = ORI[asset.orientation] + // return resolve({ + // width: asset.width, + // height: asset.height, + // path: uri, + // orientation, + // type: asset.displayName.split('.').pop(), + // duration: asset.duration / 1000, + // size: Math.round(asset.size / 1024), + // bitrate: Math.round((asset.size * 8 * 1000) / (asset.duration * 1024)), + // }) + // } else if (isSandboxPath(uri)) { + // uri = switchInternalToHapSandBox(uri) + // const fileType = uri.split('.').pop() + // const fileName = uri.split('/').pop() + // if (!fs.accessSync(uri)) { + // reject(['getVideoInfo fail, src not exist.', ErrorCode.PARAMETER_ERROR]) + // return + // } + // const file = fs.openSync(uri, fs.OpenMode.READ_WRITE) + // if (!file) { + // reject(['saveVideoToPhotosAlbum fail, src not exist.', ErrorCode.PARAMETER_ERROR]) + // return + // } + // // await new Promise(res => setTimeout(res, 500)) + // // const fileResult = await media.getFileAssets(videosfetchOp) + // // const asset = await fileResult.getFirstObject() + // const fd = file.fd + // const stat = fs.statSync(fd) + // const sizes = stat.size + // const buf = new ArrayBuffer(sizes) + // FileioBase.ohosReadSync(fd, buf) + // const videoUri = await saveMedia(fileName, buf) + // // const media = MediaLibraryBase.getMedia() + // const asset = await getFileAssetFromUri(videoUri) + // const width = Number(asset.get(photoAccessHelper.PhotoKeys.WIDTH)) + // const height = Number(asset.get(photoAccessHelper.PhotoKeys.HEIGHT)) + // const orientation = ORI[asset.get(photoAccessHelper.PhotoKeys.ORIENTATION)] + // const duration = Number(asset.get(photoAccessHelper.PhotoKeys.DURATION)) / 1000 + // const size = Math.round(Number(asset.get(photoAccessHelper.PhotoKeys.SIZE)) / 1024) + // const bitrate = Math.round((Number(asset.get(photoAccessHelper.PhotoKeys.SIZE)) * 8 * 1000) / (Number(asset.get(photoAccessHelper.PhotoKeys.DURATION)) * 1024)) + // const result = { + // width, + // height, + // path: params.src, + // orientation, + // type: fileType, + // duration, + // size, + // bitrate, + // } + // try { + // await asset.trash(true) + // await photoAccessHelper.MediaAssetChangeRequest.deleteAssets(context, [asset.uri]) + // } catch (error) { + // console.debug('[AdvancedAPI] delete tempFile fail: %s', error.message) + // } + // // fileResult.close() + // return resolve(result) + // } else { + // return reject(['get uri fail', ErrorCode.SERVICE_UNAVIALABLE]) + // } + // } catch (err) { + // console.debug(`[AdvancedAPI] getVideoInfo err %s`, JSON.stringify(err)) + // reject([err.message, err.code]) + // } + }) + } + + saveVideoToPhotosAlbum(params) { + return new Promise(async (resolve, reject) => { + const filePath = params.filePath + // const permission = await MediaLibraryBase.getPermissions() + // if (permission.perNum === -1) { + // return reject(['permission fail', ErrorCode.USER_REJECT, permission.perNum, permission.dialogShownResults]) + // } + if (typeof filePath !== 'string') { + return reject(['filePath format is not supported.', ErrorCode.PARAMETER_ERROR]) + } + console.debug('[AdvancedAPI] filePath:', filePath) + if (isFileUri(filePath)) { + const uri = filePath + const fd = getFdFromUriOrSandBoxPath(uri) + const stat = fs.statSync(fd) + const size = stat.size + const buf = new ArrayBuffer(size) + FileioBase.ohosReadSync(fd, buf) + const fileAsset = await getFileAssetFromUri(uri) + const displayName = 'VIDEO_' + new Date().getTime() + '_' + fileAsset.displayName + // uri = fileUri.getUriFromPath(uri) + const imageUri = await saveMedia(photoAccessHelper.PhotoType.VIDEO, displayName, uri, buf) + resolve({ path: imageUri }) + return + } else if (isSandboxPath(filePath)) { + let uri = filePath + if (uri.startsWith('internal://')) { + uri = switchInternalToHapSandBox(uri) + } + if (!fs.accessSync(uri)) { + reject(['saveVideoToPhotosAlbum fail, src not exist.', ErrorCode.PARAMETER_ERROR]) + return + } + const file = fs.openSync(uri, fs.OpenMode.READ_ONLY) + if (!file) { + reject(['saveVideoToPhotosAlbum fail, src not exist.', ErrorCode.PARAMETER_ERROR]) + return + } + const fd = file.fd + + // 根据文件大小定义空arrayBuffer用来写入文件 + const stat = fs.statSync(uri) + + const size = stat.size + + const buf = new ArrayBuffer(size) + + // 读取传入文件信息到缓冲区 + FileioBase.ohosReadSync(fd, buf) + + // 获取文件显示名 + const displayName = 'VIDEO_' + new Date().getTime() + '_' + filePath.split('/').splice(-1, 1).toString() + uri = fileUri.getUriFromPath(uri) + const imageUri = await saveMedia(photoAccessHelper.PhotoType.VIDEO, displayName, uri, buf) + resolve({ path: imageUri }) + return + } + reject(['filePath format is not supported.', ErrorCode.PARAMETER_ERROR]) + }) + } +} diff --git a/ohos/AdvancedAPI_OHOS/src/advancedApi/module/ASWifi/index.js b/ohos/AdvancedAPI_OHOS/src/advancedApi/module/ASWifi/index.js new file mode 100644 index 0000000000..1dd7e9011f --- /dev/null +++ b/ohos/AdvancedAPI_OHOS/src/advancedApi/module/ASWifi/index.js @@ -0,0 +1,357 @@ + +/** + * Copyright (c) Huawei Technologies Co., Ltd. 2022-2022. All rights reserved. + * Description: default description + * Author: weisufang + * Create: 04/10/2023 + * 需要权限: + * ohos.permission.LOCATION + * ohos.permission.GET_WIFI_INFO + * ohos.permission.SET_WIFI_INFO + * ohos.permission.MANAGE_WIFI_CONNECTION + * ohos.permission.GET_WIFI_INFO_INTERNAL + * ohos.permission.SET_WIFI_CONFIG + */ + +import wifi from '@ohos.wifi' +import { WifiBase } from '../../../base/bridge/wifiBase' +import { WifiBaseModule } from '../../../base/module/Wifi/WifiBaseModule' +import { isString } from '../../../base/util/checkDataType' +import { ErrorCode, WifiErrorCode } from '../../../base/util/ErrorCode' + +// eslint-disable-next-line no-unused-vars +const WIFI_ERR_CODE = { + OK: 0, // 正常 + NOT_INIT: 12000, // 未先调用 startWifi 接口 + NOT_SUPPORT: 12001, // 当前系统不支持相关能力 + ERR_PASSWORD: 12002, // 密码错误 + NOT_TURN_ON: 12005, // Android 特有,未打开 Wi-Fi 开关 + CONFIG_EXPIPIRED: 12013 // 系统保存的 Wi-Fi 配置过期,建议忘记 Wi-Fi 后重试,仅 Android 支持 +} + +export default class ASWifi extends WifiBaseModule { + constructor() { + super() + this.connectCallbacks = [] + this.connectWithPartialInfo = [] + this._connectByNetId = [] + this.wifiScanCallbacks = [] + this.connectionChange() + this.scanChange() + } + + /** + * 初始化Wi-Fi模块 + * @param {function} success - 接口调用成功的回调函数 + * @param {function} fail - 接口调用失败的回调函数 + * @param {function} complete - 接口调用结束的回调函数(调用成功、失败都会执行) + */ + startWifi (params) { + return new Promise((resolve, reject) => { + if (wifi.isWifiActive()) { + console.debug('[AdvancedAPI] enableWifi success') + resolve() + } else { + if (wifi.enableWifi()) { + console.debug('[AdvancedAPI] enableWifi success') + resolve() + } else { + console.debug('[AdvancedAPI] enableWifi fail') + reject(['wifi not turned on', WifiErrorCode.WIFI_NOT_TURNED_ON]) + } + } + }) + } + + /** + * 关闭 Wi-Fi 模块 + * @param {function} success - 接口调用成功的回调函数 + * @param {function} fail - 接口调用失败的回调函数 + * @param {function} complete - 接口调用结束的回调函数(调用成功、失败都会执行) + */ + stopWifi () { + return new Promise((resolve, reject) => { + if (!wifi.isWifiActive()) { + console.debug('[AdvancedAPI] stopWifi success') + resolve() + } else { + if (wifi.disableWifi()) { + console.debug('[AdvancedAPI] stopWifi success') + resolve() + } else { + console.debug('[AdvancedAPI] stopWifi fail') + reject(['system not support', ErrorCode.COMMON_ERROR]) + } + } + }) + } + + /** + * 获取已连接的 Wi-Fi 信息 + * @param {boolean} partialInfo - 是否需要返回部分 Wi-Fi 信息 + * @param {function} success - 接口调用成功的回调函数 + * @param {function} fail - 接口调用失败的回调函数 + * @param {function} complete - 接口调用结束的回调函数(调用成功、失败都会执行) + */ + getConnectedWifi (params = {}) { + return new Promise((resolve, reject) => { + // eslint-disable-next-line no-unused-vars + const { partialInfo = false } = params + super.getConnectedWifi(partialInfo).then(([[wifi]]) => { + resolve({ wifi: wifi }) + }, (err) => { + reject(...err) + }) + }) + } + + /** + * 请求获取 Wi-Fi 列表。wifiList 数据会在 onGetWifiList 注册的回调中返回。 + * @param {function} success - 接口调用成功的回调函数 + * @param {function} fail - 接口调用失败的回调函数 + * @param {function} complete - 接口调用结束的回调函数(调用成功、失败都会执行) + */ + getWifiList (params) { + return new Promise((resolve, reject) => { + super.scan().then(([data = []] = []) => { + resolve(...data) + }, (err) => { + reject(...err) + }) + }) + } + + /** + * 监听获取到 Wi-Fi 列表数据事件。 + * @param {function} 获取到 Wi-Fi 列表数据事件的监听函数 + */ + onGetWifiList (callback) { + if (typeof callback !== 'function') { + console.error('[AdvancedAPI] param is invalid.') + return + } + this.wifiScanCallbacks.push(callback) + } + + /** + * 移除获取到 Wi-Fi 列表数据事件的监听函数。不支持移除某个监听函数 + * @param {function} 传入的监听函数。不传此参数则移除所有监听函数。 + */ + offGetWifiList (callback) { + const index = this.wifiScanCallbacks.indexOf(callback) + if (index >= 0) { + this.wifiScanCallbacks.splice(index, 1) + } else { + this.wifiScanCallbacks = [] + } + } + + /** + * 连接 Wi-Fi。若已知 Wi-Fi 信息,可以直接利用该接口连接。 + * @param {string} SSID Wi-Fi 设备 SSID + * @param {string} BSSID Wi-Fi 设备 BSSID + * @param {string} password Wi-Fi 设备密码 + * @param {boolean} maunal 跳转到系统设置页进行连接 + * @param {boolean} partialInfo 是否需要返回部分 Wi-Fi 信息 + * @param {function} success - 接口调用成功的回调函数 + * @param {function} fail - 接口调用失败的回调函数 + * @param {function} complete - 接口调用结束的回调函数(调用成功、失败都会执行) + */ + connectWifi (params) { + return new Promise(async (resolve, reject) => { + // eslint-disable-next-line no-unused-vars + const { SSID, BSSID = '', password = '', maunal = false, partialInfo = false } = params + if (!isString(SSID)) { + console.error('[AdvancedAPI] connectWifi invalid SSID') + reject(['wifi SSID error', WifiErrorCode.PASSWORD_ERROR]) + return + } + if (!isString(BSSID)) { + console.error('[AdvancedAPI] connectWifi invalid BSSID') + reject(['wifi BSSID error', WifiErrorCode.PASSWORD_ERROR]) + return + } + if (!isString(password)) { + console.error('[AdvancedAPI] connectWifi invalid password') + reject(['wifi password error', WifiErrorCode.PASSWORD_ERROR]) + return + } + + try { + const connectedInfo = await this.getConnectedWifi() + if (connectedInfo.wifi.SSID === SSID) { + resolve() + return + } + } catch (e) { + // 如果当前没有已连接上的wifi不影响 + console.debug('[AdvancedAPI] wifi is not connected.') + } + + try { + const netId = await wifi.addDeviceConfig({ + ssid: SSID, + bssid: BSSID, + preSharedKey: password, + securityType: 3, + isHiddenSsid: false + }) + console.debug('[AdvancedAPI] addDeviceConfig success netId = %d', netId) + this._connectByNetId.push(result => { + const wifiInfo = result.wifi + if (wifiInfo.SSID === SSID) { + resolve() + } else { + reject() + } + }) + if (maunal) { // TODO: 跳转到设置wlan页面连接 + console.error('[AdvancedAPI] 不支持跳转系统wlan页面') + return + } else { + wifi.connectToNetwork(netId) + } + } catch (err) { + console.error('[AdvancedAPI] connectWifi addDeviceConfig fail err = ' + err) + reject(['system not support', ErrorCode.COMMON_ERROR]) + } + }) + } + + /** + * 监听连接上 Wi-Fi 的事件。 + * @param {function} 连接上 Wi-Fi 的事件的监听函数 + */ + onWifiConnected (callback) { + if (typeof callback !== 'function') { + console.error('[AdvancedAPI] param is invalid.') + return + } + this.connectCallbacks.push(callback) + } + + /** + * 移除连接上 Wi-Fi 的事件的监听函数。 + * @param {function} 传入的监听函数。不传此参数则移除所有监听函数。 + */ + offWifiConnected (callback) { + const index = this.connectCallbacks.indexOf(callback) + if (index >= 0) { + this.connectCallbacks.splice(index, 1) + } else { + this.connectCallbacks = [] + } + } + + // wifi连接回调 + connectionChange () { + WifiBase.connectionChange(state => { + if (state === WifiBase.StateType.ON) { + this.getConnectedWifi().then(({ wifi }) => { + wifi.state = WifiBase.StateType.ON + this.triggerConnectCallbacks({ wifi }) + this.triggerConnectWithPartialInfo({ wifi }) + this.triggerConnectById({ wifi }) + }, () => { + const wifi = { + 'BSSID': '', + 'signalStrength': 0, + 'state': WifiBase.StateType.ON, + 'secure': false, + 'SSID': '' + } + this.triggerConnectCallbacks({ wifi }) + this.triggerConnectWithPartialInfo({ wifi }) + }) + } else if (state === WifiBase.StateType.OFF) { + const wifi = { + 'BSSID': '', + 'signalStrength': 0, + 'state': WifiBase.StateType.OFF, + 'secure': false, + 'SSID': '' + } + this.triggerConnectCallbacks({ wifi }) + this.triggerConnectWithPartialInfo({ wifi }) + } + }) + } + + // wifi扫描回调 + scanChange () { + WifiBase.scanStateChange(isScan => { + if (isScan === WifiBase.ScanState.SUCCESS) { + WifiBase.getScanInfos().then(wifiInfos => { + console.debug('[AdvancedAPI] onGetWifiList getScanInfos success') + const wifiList = wifiInfos.map(item => { + return { + BSSID: item.bssid, + SSID: item.ssid, + frequency: item.frequency, + signalStrength: super.getSignalStrength(item.rssi), + secure: super.isSecure(item.capabilities) + } + }) + this.triggerScanCallbacks({ wifiList }) + }) + } + }) + } + + triggerConnectCallbacks (result) { + console.debug('[AdvancedAPI] triggerConnectCallbacks') + result.errMsg = 'onWifiConnected:ok' + result.errCode = 0 + this.connectCallbacks.forEach(cb => { + cb(result) + }) + } + + triggerConnectById (result) { + console.debug('[AdvancedAPI] triggerConnectById') + this._connectByNetId.forEach(cb => { + cb(result) + }) + this._connectByNetId = [] + } + + triggerScanCallbacks (result) { + console.debug('[AdvancedAPI] wifiScanCallbacks') + this.wifiScanCallbacks.forEach(cb => { + cb(result) + }) + } + + /** + * 监听连接上 Wi-Fi 的事件。 + * @param {function} 连接上 Wi-Fi 的事件的监听函数 + */ + onWifiConnectedWithPartialInfo (callback) { + if (typeof callback !== 'function') { + console.error('[AdvancedAPI] param is invalid.') + return + } + this.connectWithPartialInfo.push(callback) + } + + /** + * 移除连接上 Wi-Fi 的事件的监听函数。 + * @param {function} 传入的监听函数。不传此参数则移除所有监听函数。 + */ + offWifiConnectedWithPartialInfo (callback) { + const index = this.connectWithPartialInfo.indexOf(callback) + if (index >= 0) { + this.connectWithPartialInfo.splice(index, 1) + } else { + this.connectWithPartialInfo = [] + } + } + + triggerConnectWithPartialInfo (result) { + console.debug('[AdvancedAPI] triggerConnectWithPartialInfo') + const wifi = { SSID: result.wifi.SSID } + this.connectWithPartialInfo.forEach(cb => { + cb({ wifi }) + }) + } +} diff --git a/ohos/AdvancedAPI_OHOS/src/advancedApi/module/index.js b/ohos/AdvancedAPI_OHOS/src/advancedApi/module/index.js new file mode 100644 index 0000000000..35006f71e5 --- /dev/null +++ b/ohos/AdvancedAPI_OHOS/src/advancedApi/module/index.js @@ -0,0 +1,59 @@ +import ASDevice from './ASDevice/index' +import ASLocation from './ASLocation/index' +import ASPhone from './ASPhone/index' +import ASRequest from './ASRequest/index' +import ASBluetooth from './ASBluetooth/index' +import ASRouter from './ASRouter/index' +import ASWifi from './ASWifi/index' +import ASAuthentication from './ASAuthentication' +import ASAccelerometer from './ASAccelerometer/index' +import ASCompass from './ASCompass/index' +import ASGyroscope from './ASGyroscope/index' +import ASContact from './ASContact/index' +import ASVibrator from './ASVibrator/index' +import ASCapture from './ASCapture/index' +import ASKeyboard from './ASKeyboard/index' +import ASImage from './ASImage/index' +import ASAudio from './ASAudio/index' +import ASVideo from './ASVideo/index' +import ASBGAudio from './ASBGAudio/index' +import ASFile from './ASFile/index' +import ASBrightness from './ASBrightness/index' +import ASInterceptor from './ASInterceptor/index' +import ASScan from './ASScan/index' + +const asModulesMap = new Map() +asModulesMap.set('ASDevice', ASDevice) +asModulesMap.set('ASLocation', ASLocation) +asModulesMap.set('ASPhone', ASPhone) +asModulesMap.set('ASRequest', ASRequest) +asModulesMap.set('ASRouter', ASRouter) +asModulesMap.set('ASBluetooth', ASBluetooth) +asModulesMap.set('ASWifi', ASWifi) +asModulesMap.set('ASAuthentication', ASAuthentication) +asModulesMap.set('ASAccelerometer', ASAccelerometer) +asModulesMap.set('ASCompass', ASCompass) +asModulesMap.set('ASGyroscope', ASGyroscope) +asModulesMap.set('ASContact', ASContact) +asModulesMap.set('ASVibrator', ASVibrator) +asModulesMap.set('ASCapture', ASCapture) +asModulesMap.set('ASKeyboard', ASKeyboard) +asModulesMap.set('ASImage', ASImage) +asModulesMap.set('ASBrightness', ASBrightness) +asModulesMap.set('ASFile', ASFile) +asModulesMap.set('ASAudio', ASAudio) +asModulesMap.set('ASBGAudio', ASBGAudio) +asModulesMap.set('ASVideo', ASVideo) +asModulesMap.set('ASInterceptor', ASInterceptor) +asModulesMap.set('ASScan', ASScan) + +const moduleInstance = {} + +export function requireAPI (moduleName) { + if (!moduleInstance[moduleName]) { + console.debug('[AdvancedAPI] create %s', moduleName) + const XModule = asModulesMap.get(moduleName) + moduleInstance[moduleName] = new XModule() + } + return moduleInstance[moduleName] +} diff --git a/ohos/AdvancedAPI_OHOS/src/advancedApi/module/interface.js b/ohos/AdvancedAPI_OHOS/src/advancedApi/module/interface.js new file mode 100644 index 0000000000..9051d71722 --- /dev/null +++ b/ohos/AdvancedAPI_OHOS/src/advancedApi/module/interface.js @@ -0,0 +1,317 @@ +import { interceptCallback } from '../callback/callback-intercept' +import JSCallback, { jsCallbackMap } from '../callback/JSCallback' + +import { + getSystemInfoSync, + getDeviceInfo, + getWindowInfo, + getAppBaseInfo, + getAppAuthorizeSetting, + getSystemSetting, + openAppAuthorizeSetting +} from '../as/device/system' +import { navigateTo, redirectTo, navigateBack } from '../as/router/navigate' +import { + getLocation, + onLocationChange, + offLocationChange, + onLocationChangeError, + offLocationChangeError, + startLocationUpdate, + startLocationUpdateBackground, + stopLocationUpdate +} from '../as/location/location' +import { makePhoneCall } from '../as/telephony/telephony' +import { request, uploadFile, downloadFile } from '../as/request/request' +import { + openBluetoothAdapter, + startBluetoothDevicesDiscovery, + onBluetoothDeviceFound, + offBluetoothDeviceFound, + stopBluetoothDevicesDiscovery, + onBluetoothAdapterStateChange, + offBluetoothAdapterStateChange, + getConnectedBluetoothDevices, + getBluetoothAdapterState, + closeBluetoothAdapter, + getBluetoothDevices, + setBLEMTU, + writeBLECharacteristicValue, + readBLECharacteristicValue, + onBLEConnectionStateChange, + offBLEConnectionStateChange, + onBLECharacteristicValueChange, + offBLECharacteristicValueChange, + notifyBLECharacteristicValueChange, + getBLEDeviceServices, + getBLEDeviceRSSI, + getBLEDeviceCharacteristics, + createBLEConnection, + closeBLEConnection +} from '../as/bluetooth/bluetooth' +import { + startWifi, + stopWifi, + getConnectedWifi, + getWifiList, + onGetWifiList, + offGetWifiList, + connectWifi, + onWifiConnected, + offWifiConnected, + onWifiConnectedWithPartialInfo, + offWifiConnectedWithPartialInfo +} from '../as/device/wifi' +import { startSoterAuthentication, checkIsSupportSoterAuthentication, checkIsSoterEnrolledInDevice } from '../as/device/authenication' +import { + onAccelerometerChange, + offAccelerometerChange, + startAccelerometer, + stopAccelerometer +} from '../as/device/accelerometer' +import { + onCompassChange, + offCompassChange, + startCompass, + stopCompass +} from '../as/device/compass' +import { + onGyroscopeChange, + startGyroscope, + stopGyroscope +} from '../as/device/gyroscope' +import { addPhoneContact } from '../as/device/contact' +import { vibrate, vibrateLong, vibrateShort } from '../as/device/vibrate' +import { onUserCaptureScreen, offUserCaptureScreen } from '../as/device/capture' +import { hideKeyboard, onKeyboardHeightChange, offKeyboardHeightChange } from '../as/keyboard/keyboard' +import { login, getUserInfo } from '../as/account/account' +import { + chooseImage, + getImageInfo, + saveImageToPhotosAlbum, + compressImage +} from '../as/media/image' +import { setScreenBrightness, getScreenBrightness, setKeepScreenOn } from '../as/device/brightness' +import { getFileInfo, getSavedFileInfo, getSavedFileList, removeSavedFile, saveFile, getFileSystemManager, openDocument } from '../as/file/file' +import { + createInnerAudioContext +} from '../as/media/audio' +import { + saveVideoToPhotosAlbum, + getVideoInfo, +} from '../as/media/video' +import { scanCode } from '../as/scan/scan' + +/** + * needPromise默认值是true:表示默认promise化 + * [methodName]: { method: [method], needPromise: {boolean}, needCallback: {boolean} } + * needPromise: false; needCallback:false 表示不需要封装promise和JSCallback,会直接把cp的参数透传给接口 + */ +export const asInterfaceList = { + // 设备系统 + getSystemInfoSync: { method: getSystemInfoSync, needPromise: false, needCallback: false }, + getDeviceInfo: { method: getDeviceInfo, needPromise: false }, + getWindowInfo: { method: getWindowInfo, needPromise: false }, + getAppBaseInfo: { method: getAppBaseInfo, needPromise: false }, + getAppAuthorizeSetting: { method: getAppAuthorizeSetting, needPromise: false }, + getSystemSetting: { method: getSystemSetting, needPromise: false }, + openAppAuthorizeSetting: { method: openAppAuthorizeSetting }, + + // 地理位置 + getLocation: { method: getLocation }, + onLocationChange: { method: onLocationChange }, + offLocationChange: { method: offLocationChange, needPromise: false }, + startLocationUpdate: { method: startLocationUpdate }, + startLocationUpdateBackground: { method: startLocationUpdateBackground }, + stopLocationUpdate: { method: stopLocationUpdate }, + onLocationChangeError: { method: onLocationChangeError }, + offLocationChangeError: { method: offLocationChangeError }, + // 电话 + makePhoneCall: { method: makePhoneCall }, + + // 网络 + request: { method: request }, + uploadFile: { method: uploadFile }, + downloadFile: { method: downloadFile }, + + // 页面和路由 + navigateTo: { method: navigateTo }, + redirectTo: { method: redirectTo }, + navigateBack: { method: navigateBack }, + + // 蓝牙 + openBluetoothAdapter: { method: openBluetoothAdapter }, + startBluetoothDevicesDiscovery: { method: startBluetoothDevicesDiscovery }, + onBluetoothDeviceFound: { method: onBluetoothDeviceFound, needPromise: false, needCallback: false }, + offBluetoothDeviceFound: { method: offBluetoothDeviceFound, needPromise: false, needCallback: false }, + stopBluetoothDevicesDiscovery: { method: stopBluetoothDevicesDiscovery }, + onBluetoothAdapterStateChange: { method: onBluetoothAdapterStateChange, needPromise: false, needCallback: false }, + offBluetoothAdapterStateChange: { method: offBluetoothAdapterStateChange, needPromise: false, needCallback: false }, + getConnectedBluetoothDevices: { method: getConnectedBluetoothDevices }, + getBluetoothAdapterState: { method: getBluetoothAdapterState }, + closeBluetoothAdapter: { method: closeBluetoothAdapter }, + getBluetoothDevices: { method: getBluetoothDevices }, + // 低功耗蓝牙 + setBLEMTU: { method: setBLEMTU }, + writeBLECharacteristicValue: { method: writeBLECharacteristicValue }, + readBLECharacteristicValue: { method: readBLECharacteristicValue }, + onBLEConnectionStateChange: { method: onBLEConnectionStateChange, needPromise: false, needCallback: false }, + offBLEConnectionStateChange: { method: offBLEConnectionStateChange, needPromise: false, needCallback: false }, + onBLECharacteristicValueChange: { method: onBLECharacteristicValueChange, needPromise: false, needCallback: false }, + offBLECharacteristicValueChange: { method: offBLECharacteristicValueChange, needPromise: false, needCallback: false }, + notifyBLECharacteristicValueChange: { method: notifyBLECharacteristicValueChange }, + getBLEDeviceServices: { method: getBLEDeviceServices }, + getBLEDeviceRSSI: { method: getBLEDeviceRSSI }, + getBLEDeviceCharacteristics: { method: getBLEDeviceCharacteristics }, + createBLEConnection: { method: createBLEConnection }, + closeBLEConnection: { method: closeBLEConnection }, + + // 传感器 + onAccelerometerChange: { method: onAccelerometerChange, needPromise: false, needCallback: false }, + offAccelerometerChange: { method: offAccelerometerChange, needPromise: false, needCallback: false }, + startAccelerometer: { method: startAccelerometer }, + stopAccelerometer: { method: stopAccelerometer }, + // 当接口参数中包含开发者的回调接口,比如监听的场景,接口框架不需要额外创建callBack对象,此时通过needCallback关键字控制 + onCompassChange: { method: onCompassChange, needPromise: false, needCallback: false }, + offCompassChange: { method: offCompassChange, needPromise: false, needCallback: false }, + startCompass: { method: startCompass }, + stopCompass: { method: stopCompass }, + onGyroscopeChange: { method: onGyroscopeChange, needPromise: false, needCallback: false }, + startGyroscope: { method: startGyroscope }, + stopGyroscope: { method: stopGyroscope }, + // wifi + startWifi: { method: startWifi }, + stopWifi: { method: stopWifi }, + getConnectedWifi: { method: getConnectedWifi }, + getWifiList: { method: getWifiList }, + onGetWifiList: { method: onGetWifiList, needPromise: false, needCallback: false }, + offGetWifiList: { method: offGetWifiList, needPromise: false, needCallback: false }, + connectWifi: { method: connectWifi }, + onWifiConnected: { method: onWifiConnected, needPromise: false, needCallback: false }, + offWifiConnected: { method: offWifiConnected, needPromise: false, needCallback: false }, + onWifiConnectedWithPartialInfo: { method: onWifiConnectedWithPartialInfo, needPromise: false, needCallback: false }, + offWifiConnectedWithPartialInfo: { method: offWifiConnectedWithPartialInfo, needPromise: false, needCallback: false }, + + // 生物认证 + startSoterAuthentication: { method: startSoterAuthentication }, + checkIsSupportSoterAuthentication: { method: checkIsSupportSoterAuthentication }, + checkIsSoterEnrolledInDevice: { method: checkIsSoterEnrolledInDevice }, + + // 联系人 + addPhoneContact: { method: addPhoneContact }, + + // 振动 + vibrate: { method: vibrate }, + vibrateLong: { method: vibrateLong }, + vibrateShort: { method: vibrateShort }, + + // 截屏事件 + onUserCaptureScreen: { method: onUserCaptureScreen, needPromise: false, needCallback: false }, + offUserCaptureScreen: { method: offUserCaptureScreen, needPromise: false, needCallback: false }, + + // 键盘 + hideKeyboard: { method: hideKeyboard }, + onKeyboardHeightChange: { method: onKeyboardHeightChange, needPromise: false, needCallback: false }, + offKeyboardHeightChange: { method: offKeyboardHeightChange, needPromise: false, needCallback: false }, + + // 帐号 + login: { method: login }, + getUserInfo: { method: getUserInfo }, + + // 媒体 图片 + chooseImage: { method: chooseImage }, + getImageInfo: { method: getImageInfo }, + saveImageToPhotosAlbum: { method: saveImageToPhotosAlbum }, + compressImage: { method: compressImage }, + + // 屏幕亮度 + setScreenBrightness: { method: setScreenBrightness }, + getScreenBrightness: { method: getScreenBrightness }, + setKeepScreenOn: { method: setKeepScreenOn }, + + // 文件 + saveFile: { method: saveFile }, + getSavedFileList: { method: getSavedFileList }, + getSavedFileInfo: { method: getSavedFileInfo }, + removeSavedFile: { method: removeSavedFile }, + getFileInfo: { method: getFileInfo }, + openDocument: { method: openDocument }, + getFileSystemManager: { method: getFileSystemManager, needPromise: false, needCallback: false }, + + // 基础 + + // 媒体 录音管理 + + // 媒体 音频 + createInnerAudioContext: { method: createInnerAudioContext, needPromise: false, needCallback: false }, + + // 媒体 视频 + saveVideoToPhotosAlbum: { method: saveVideoToPhotosAlbum }, + getVideoInfo: { method: getVideoInfo }, + + // 二维码扫描 + scanCode: { method: scanCode }, +} + +function invokeModule (moduleName, ...args) { + console.debug('[AdvancedAPI] invokeModule moduleName = %s', moduleName) + const id = args.pop() + if (typeof id === 'number') { + let callback = jsCallbackMap.get(id) + if (!callback) { + callback = new JSCallback({ id }) + jsCallbackMap.set(id, callback) + } + args.push(callback) + } else { + args.push(id) + } + const values = asInterfaceList[moduleName] + triggerInterceptInvoke(moduleName, args) + const result = values.method.apply(null, args) + triggerInterceptReturnValue(moduleName, result) + return result +} + +function triggerInterceptInvoke (moduleName, args) { + const interceptor = requireAPI('ASInterceptor') + if (asInterfaceList[moduleName].needCallback !== false) { + const params = [...args] + params.pop() + interceptor.invoke(moduleName, params) + } +} + +function triggerInterceptReturnValue (moduleName, args) { + const interceptor = requireAPI('ASInterceptor') + interceptor.returnValue(moduleName, args) +} + +export function createAs() { + const as = {} + const moduleNames = Object.keys(asInterfaceList) + moduleNames.forEach(moduleName => { + Object.defineProperty(as, moduleName, { + get: () => { + return (...args) => { + const cbResult = interceptCallback(args, + moduleName, + asInterfaceList[moduleName].needPromise, + asInterfaceList[moduleName].needCallback) + args = cbResult.args || [] + const promise = cbResult.promise + const result = invokeModule(moduleName, ...args) + if (promise) { + return promise.promise + } + return result + } + } + }) + }) + return as +} + +const as = createAs() + +export default as diff --git a/ohos/AdvancedAPI_OHOS/src/advancedApi/util/index.js b/ohos/AdvancedAPI_OHOS/src/advancedApi/util/index.js new file mode 100644 index 0000000000..30fb5af2f0 --- /dev/null +++ b/ohos/AdvancedAPI_OHOS/src/advancedApi/util/index.js @@ -0,0 +1,204 @@ +import { isString, isNumber } from '../../base/util/checkDataType' +import { colors } from '../../base/util/colors' +import { context } from '../../base/bridge/abilityBase' +import fs from '@ohos.file.fs' +import photoAccessHelper from '@ohos.file.photoAccessHelper' +import dataSharePredicates from '@ohos.data.dataSharePredicates' +import { MediaLibraryBase } from '../../base/bridge/mediaLibraryBase' + +// 转换背景色为Hex argb +export function convertColorToHexARGB(color, opacity) { + if (!isString(color)) { + color = '#FFFFFF' + } + if (color.trim().match(/^[A-z]+$/) && colors[color]) { + color = `rgb(${colors[color].join(',')})` + } + if (color === 'transparent') { + return '#00000000' + } + + if (!isNumber(opacity) || opacity < 0 || opacity > 1) { + opacity = 1 + } + + if (color.startsWith('rgb')) { + const arr = color.split(',') + if (arr.length < 3) { + return color + } + if (arr.length === 4) { + const temp = arr.pop() + arr.unshift(temp) + } else { + arr.unshift(String(opacity)) + } + + return arr.reduce((prev, current, index) => { + let hex = current.replace(/[^\d\\.]/gi, '') + hex = index === 0 ? parseInt(hex * 255) : parseInt(hex) + hex = hex.toString(16).toUpperCase() + if (hex.length === 1) { + hex = `0${hex}` + } + return prev + hex + }, '#') + } + + if (color.startsWith('#')) { + // #fff ----> #ffffff + if (color.length === 4) { + color = `#${color[1]}${color[1]}${color[2]}${color[2]}${color[3]}${color[3]}` + } + if (color.length === 7) { + const hex = color.slice(1) + let opacityHex = parseInt(opacity * 255).toString(16).toUpperCase() + if (opacityHex.length === 1) { + opacityHex = `0${opacityHex}` + } + return `#${opacityHex}${hex}` + } + } + + return color +} + +export function switchInternalToHapSandBox(path) { + if (path.startsWith('internal://bundle/')) { + return path.replace('internal://bundle', context.bundleCodeDir) + } + if (path.startsWith('internal://cache/')) { + return path.replace('internal://cache', context.cacheDir) + } + if (path.startsWith('internal://files/')) { + return path.replace('internal://files', context.filesDir) + } + if (path.startsWith('internal://preferences/')) { + return path.replace('internal://preferences', context.preferencesDir) + } + if (path.startsWith('internal://temp/')) { + return path.replace('internal://temp', context.tempDir) + } + if (path.startsWith('internal://database/')) { + return path.replace('internal://database', context.databaseDir) + } + if (path.startsWith('internal://distributedFiles/')) { + return path.replace('internal://distributedFiles', context.distributedFilesDir) + } + return path +} +export function switchHapSandBoxToInternal(path) { + if (path.startsWith(context.bundleCodeDir)) { + return path.replace(context.bundleCodeDir, 'internal://bundle') + } + if (path.startsWith(context.cacheDir)) { + return path.replace(context.cacheDir, 'internal://cache') + } + if (path.startsWith(context.filesDir)) { + return path.replace(context.filesDir, 'internal://files') + } + if (path.startsWith(context.preferencesDir)) { + return path.replace(context.preferencesDir, 'internal://preferences') + } + if (path.startsWith(context.tempDir)) { + return path.replace(context.tempDir, 'internal://temp') + } + if (path.startsWith(context.databaseDir)) { + return path.replace(context.databaseDir, 'internal://database') + } + if (path.startsWith(context.distributedFilesDir)) { + return path.replace(context.distributedFilesDir, 'internal://distributedFiles') + } + return path +} +export function isFileUri(path) { + return path && typeof (path) === 'string' && (path.startsWith('file://') || path.startsWith('datashare://')) +} + +export function isSandboxPath(path) { + return path && typeof (path) === 'string' && (path.startsWith('/data/storage/') || path.startsWith('internal://')) +} +export function getFdFromUriOrSandBoxPath(uri) { + try { + const file = fs.openSync(uri, fs.OpenMode.READ_ONLY) + return file.fd + } catch (error) { + console.info(`[AdvancedAPI] Can not get file from uri: ${uri} `) + } + throw new Error('file is not exist') +} + +export async function getFileAssetFromUri(uri) { + try { + const permission = await MediaLibraryBase.getPermissions() + if (permission.perNum === -1) { + console.debug(`[AdvancedAPI] permission fail`) + } + const phAccessHelper = photoAccessHelper.getPhotoAccessHelper(context) + const predicates = new dataSharePredicates.DataSharePredicates() + console.debug(`[AdvancedAPI] getFileAssetFromUri uri: ${uri} `) + predicates.equalTo(photoAccessHelper.PhotoKeys.URI, uri.toString()) + const fetchOption = { + fetchColumns: [ + photoAccessHelper.PhotoKeys.URI, + photoAccessHelper.PhotoKeys.PHOTO_TYPE, + photoAccessHelper.PhotoKeys.SIZE, + photoAccessHelper.PhotoKeys.DURATION, + photoAccessHelper.PhotoKeys.WIDTH, + photoAccessHelper.PhotoKeys.HEIGHT, + photoAccessHelper.PhotoKeys.TITLE, + photoAccessHelper.PhotoKeys.ORIENTATION, + ], + predicates: predicates + } + const fetchResult = await phAccessHelper.getAssets(fetchOption) + console.debug(`[AdvancedAPI] getFileAssetFromUri fetchResult: ${JSON.stringify(fetchResult)} `) + const asset = await fetchResult.getFirstObject() + console.debug(`[AdvancedAPI] getFileAssetFromUri asset: ${JSON.stringify(asset)} `) + fetchResult.close() + return asset + } catch (err) { + console.debug(`[AdvancedAPI] getAsset is fail!,${err}`) + } +} + +export function pathToCache(path) { + try { + const srcDirUriLocal = switchInternalToHapSandBox(path) + const fileName = srcDirUriLocal.slice(srcDirUriLocal.lastIndexOf('/')) + const dstDirUriLocal = context.cacheDir + fileName + fs.copyFile(srcDirUriLocal, dstDirUriLocal, (err) => { + if (err) { + console.info(`[AdvancedAPI] Failed to copy: ${JSON.stringify(err)}`) + return + } + }) + return switchHapSandBoxToInternal(dstDirUriLocal) + } catch (err) { + console.error(`[AdvancedAPI] to copy: ${JSON.stringify(err)}`) + } +} + +export async function saveMedia(photoType, displayName, uri, buffer) { + try { + const phAccessHelper = photoAccessHelper.getPhotoAccessHelper(context) + const mediaType = displayName.split('.').pop().toString() + const mediaName = displayName.split('.').shift().toString() + const photoCreationConfig = [ + { + title: mediaName.toString(), + fileNameExtension: mediaType.toString(), + photoType: photoType, + } + ] + const srcFileUris = [uri.toString()] + const phUris = await phAccessHelper.showAssetsCreationDialog(srcFileUris, photoCreationConfig) + const phUri = phUris[0] + const file = fs.openSync(phUri, fs.OpenMode.READ_WRITE) + await fs.write(file.fd, buffer) + fs.closeSync(file) + return phUri + } catch (err) { + console.error(`[AdvancedAPI] saveMedia is fail!: ${JSON.stringify(err)}`) + } +} diff --git a/ohos/AdvancedAPI_OHOS/src/base/bridge/abilityBase.js b/ohos/AdvancedAPI_OHOS/src/base/bridge/abilityBase.js new file mode 100644 index 0000000000..1d88d34f20 --- /dev/null +++ b/ohos/AdvancedAPI_OHOS/src/base/bridge/abilityBase.js @@ -0,0 +1,70 @@ +/** + * Copyright (c) Huawei Technologies Co., Ltd. 2022-2022. All rights reserved. + * Description: ohos ability + * Author: weisufang + * Create: 03/7/2022 + * Notes: N/A + */ + +import abilityFeatureAbility from '@ohos.ability.featureAbility' + +let context = abilityFeatureAbility.getContext() +function initContextOnStageModel (contextOnStageMode) { + context = contextOnStageMode + if (!context.startAbilityForResult) { + context.startAbilityForResult = context.startAbility + } + context.getAbilityInfo = function() { + return new Promise((resolve, reject) => { + try { + resolve(this.abilityInfo) + } catch (error) { + reject(error) + } + }) + } + context.getFilesDir = function() { + return new Promise((resolve, reject) => { + try { + resolve(this.filesDir) + } catch (error) { + reject(error) + } + }) + } + context.getCacheDir = function() { + return new Promise((resolve, reject) => { + try { + resolve(this.cacheDir) + } catch (error) { + reject(error) + } + }) + } +} + +class AbilityBase { + static abilityInfo = {} + + static hasAbilityInfo = false + + static getAbilityInfo () { + return new Promise((resolve, reject) => { + if (this.hasAbilityInfo) { + resolve(this.abilityInfo) + return + } + context.getAbilityInfo().then(data => { + this.hasAbilityInfo = true + this.abilityInfo = data + console.log('[QAFAPI] getAbilityInfo successful. ') + resolve(data) + }).catch((error) => { + console.error('[QAFAPI] getAbilityInfo failed. Cause: ' + JSON.stringify(error)) + reject(error) + }) + }) + } +} + +export { abilityFeatureAbility, context, AbilityBase, initContextOnStageModel } diff --git a/ohos/AdvancedAPI_OHOS/src/base/bridge/bluetoothBase.js b/ohos/AdvancedAPI_OHOS/src/base/bridge/bluetoothBase.js new file mode 100644 index 0000000000..f7c9a699fb --- /dev/null +++ b/ohos/AdvancedAPI_OHOS/src/base/bridge/bluetoothBase.js @@ -0,0 +1,185 @@ +import bluetoothManager from '@ohos.bluetoothManager' +import access from '@ohos.bluetooth.access'; +import ble from '@ohos.bluetooth.ble'; +import connection from '@ohos.bluetooth.connection'; +import abilityAccessCtrl from '@ohos.abilityAccessCtrl' +import {context} from './abilityBase'; +// 扫描模式配置项 +export const SCAN_MODE = { + LIMITED: 5, + DURATION: 0 +} +export class BluetoothBase { + + static getPermissions() { + // 权限列表 + const arrMdl = ['ohos.permission.ACCESS_BLUETOOTH']; // 允许应用接入蓝牙并使用蓝牙能力 + const atManager = abilityAccessCtrl.createAtManager(); + return new Promise(async resolve => { + const { authResults } = await atManager.requestPermissionsFromUser(context, arrMdl) + if (authResults[0] === 0) { + resolve(true); // 通过用户许可 + }else { + resolve(false); // 未通过用户许可 + } + }) + } + + // 订阅蓝牙连接状态改变事件 + static onStateChange(callback) { + try { + return access.on('stateChange', callback) + } catch (err) { + console.warn('[AdvancedAPI] on bondStateChange fail') + } + } + + // 订阅蓝牙设备发现上报事件 + static on(onReceiveEvent) { + try { + return connection.on('bluetoothDeviceFind', onReceiveEvent) + } catch (err) { + console.warn('[AdvancedAPI] on fail') + } + } + + // 订阅低功耗设备发现上报事件 + static onBLE(onReceiveEvent) { + try { + ble.on('BLEDeviceFind', onReceiveEvent) + } catch (err) { + console.warn('[AdvancedAPI] BLE.on.BLEDeviceFind fail') + } + } + + // 创建client端实例 + static createGattClientDevice(deviceId) { + try { + return ble.createGattClientDevice(deviceId) + } catch (err) { + console.warn('[AdvancedAPI] createGattClientDevice fail') + } + } + // 打开蓝牙 + static enableBluetooth() { + try { + return access.enableBluetooth() + } catch (err) { + console.warn('[AdvancedAPI] enableBluetooth fail') + } + } + + // 关闭蓝牙 + static disableBluetooth() { + try { + return access.disableBluetooth() + } catch (err) { + console.warn('[AdvancedAPI] disableBluetooth fail') + } + } + + // 蓝牙开关状态 + static bluetoothState() { + try { + return access.getState() + } catch (err) { + // console.warn('[AdvancedAPI] getState fail') + console.error('[AdvancedAPI] getState fail, errCode: ' + err.code + ', errMessage: ' + err.message); + } + } + + // 开启蓝牙扫描 + static startBluetoothDiscovery() { + // 设置蓝牙扫描模式为可连接limited发现模式,设置为0为持续可发现,设置成功返回true + connection.setBluetoothScanMode( + connection.ScanMode.SCAN_MODE_LIMITED_DISCOVERABLE, + SCAN_MODE.DURATION + ) + + // 开启蓝牙扫描,成功返回true,否则返回false + try { + return connection.startBluetoothDiscovery() + } catch (err) { + console.warn('[AdvancedAPI] startBluetoothDiscovery fail') + } + } + + // 取消订阅蓝牙设备发现上报事件 + static off() { + try { + return connection.off('bluetoothDeviceFind') + } catch (err) { + console.warn('[AdvancedAPI] off fail') + } + } + + // 获取对端蓝牙设备的名称 + static getRemoteDeviceName(deviceId) { + try { + return connection.getRemoteDeviceName(deviceId) + } catch (err) { + console.warn('[AdvancedAPI] getRemoteDeviceName fail') + } + } + + // 关闭蓝牙扫描 + static stopBluetoothDiscovery() { + // 关闭蓝牙扫描,成功返回true,否则返回false + try { + return connection.stopBluetoothDiscovery() + } catch (err) { + console.warn('[AdvancedAPI] no need to stop') + } + } + + // 开启低功耗蓝牙扫描 + static startBLEScan(interval) { + try { + ble.startBLEScan(null, { + interval, + dutyMode: ble.ScanDuty.SCAN_MODE_LOW_POWER, + matchMode: ble.MatchMode.MATCH_MODE_AGGRESSIVE, + }) + } catch (err) { + console.error( + '[QAFAPI] startBLEScan errCode:' + err.code + ',errMessage:' + err.message + ) + } + } + + // 关闭低功耗蓝牙扫描 + static stopBLEScan() { + try { + ble.stopBLEScan() + } catch (err) { + console.error('[QAFAPI] stopBLEScan errCode:' + err.code + ',errMessage:' + err.message) + } + } + + // 取消订阅低功耗设备发现上报事件 + static offBLE() { + try { + ble.off('BLEDeviceFind') + } catch (err) { + console.warn('[AdvancedAPI] BLE.off.BLEDeviceFind fail') + } + } + + // 获取已经连接的设备地址列表 + static getProfile(ProfileId) { + try { + const a2dpSrc = bluetoothManager.getProfileInstance(ProfileId) + return a2dpSrc.getConnectionDevices() + } catch (err) { + console.warn('[AdvancedAPI] getProfileInstance fail') + } + } + + static getConnectedBLEDevices() { + try { + return ble.getConnectedBLEDevices() + } catch (err) { + console.error('[AdvancedAPI]getConnectedBLEDevices errCode:' + err.code + ',errMessage:' + err.message) + } + } +} diff --git a/ohos/AdvancedAPI_OHOS/src/base/bridge/brightnessBase.js b/ohos/AdvancedAPI_OHOS/src/base/bridge/brightnessBase.js new file mode 100644 index 0000000000..709e30757f --- /dev/null +++ b/ohos/AdvancedAPI_OHOS/src/base/bridge/brightnessBase.js @@ -0,0 +1,19 @@ +import { context } from './abilityBase' +import settings from '@ohos.settings' + +const name = settings.display.SCREEN_BRIGHTNESS_STATUS +export class BrightnessBase { + static ohoGetValue() { + const SETTINGMAX = 100 + const VAlUEMAX = 255 + try { + // 获取数据项亮度的值(该数据项在数据库中已存在) + const value = settings.getValueSync(context, name, '1') + console.log('[AdvancedAPI] success to get brightness. value:' + value) + Math.round(value * (VAlUEMAX / SETTINGMAX)) + return value + } catch (error) { + console.log('[QAFAPI] Failed to get brightness. Cause:' + JSON.stringify(error)) + } + } +} diff --git a/ohos/AdvancedAPI_OHOS/src/base/bridge/deviceBase.js b/ohos/AdvancedAPI_OHOS/src/base/bridge/deviceBase.js new file mode 100644 index 0000000000..11a0c2e897 --- /dev/null +++ b/ohos/AdvancedAPI_OHOS/src/base/bridge/deviceBase.js @@ -0,0 +1,14 @@ +/** + * Copyright (c) Huawei Technologies Co., Ltd. 2022-2022. All rights reserved. + * Description: @ohos.deviceInfo + * Author: wangtianpeng + * Create: 03/14/2022 + * Notes: N/A + */ + +import deviceInfo from '@ohos.deviceInfo' +export class DeivceBase { + static getDeviceInfo () { + return deviceInfo + } +} diff --git a/ohos/AdvancedAPI_OHOS/src/base/bridge/displayBase.js b/ohos/AdvancedAPI_OHOS/src/base/bridge/displayBase.js new file mode 100644 index 0000000000..59f4ddd604 --- /dev/null +++ b/ohos/AdvancedAPI_OHOS/src/base/bridge/displayBase.js @@ -0,0 +1,21 @@ +/** + * Copyright (c) Huawei Technologies Co., Ltd. 2022-2022. All rights reserved. + * Description: @ohos.display + * Author: wangtianpeng + * Create: 03/14/2022 + * Notes: N/A + */ + +import display from '@ohos.display' + +export class DisplayBase { + static ohosGetDisplay () { + let displayClass = null + try { + displayClass = display.getDefaultDisplaySync(); + } catch (exception) { + console.error(`[QAFAPI] display error message: ${JSON.stringify(exception)}`); + } + return displayClass + } +} diff --git a/ohos/AdvancedAPI_OHOS/src/base/bridge/fileioBase.js b/ohos/AdvancedAPI_OHOS/src/base/bridge/fileioBase.js new file mode 100644 index 0000000000..a2b24ca732 --- /dev/null +++ b/ohos/AdvancedAPI_OHOS/src/base/bridge/fileioBase.js @@ -0,0 +1,56 @@ +import fs from '@ohos.file.fs' +import fileuri from '@ohos.file.fileuri' +export class FileioBase { + static ohosOpendirSync(path) { + return new OhosOpendir(path) + } + + // 同步读取文件 + static ohosReadSync(fd, buf) { + return fs.readSync(fd, buf) + } + static ohosUnlinkSync(path) { + return fs.unlinkSync(path) + } + static ohosCopy (src, dest, mode = 0) { + return fs.copyFile(src, dest, mode) + } + static ohosMkdirSync(path, mode = 0o775) { + return fs.mkdirSync(path) + } + static ohosReadTextSync(filePath, options) { + return fs.readTextSync(filePath, options) + } + + // 同步获取文件资源信息 + static ohosStatSync(path) { + return fs.statSync(path) + } + + // 同步打开文件获取描述符 + static ohosOpenSync(path, flags, mode = 0o666) { + if (path && typeof (path) === 'string' && path.startsWith('/data/storage/')) { + path = fileuri.getUriFromPath(path) + } + return fs.openSync(path, flags) + } + + // 同步写入文件 + static ohosWriteSync(fd, buffer, options = {}) { + return fs.writeSync(fd, buffer, options) + } + + static ohosAccessSync(path, mode = 0) { + return fs.accessSync(path) + } +} +class OhosOpendir { + constructor(path) { + this.dir = fs.listFileSync(path) + } + + ohosReadsync() { + return this.dir + } +} + diff --git a/ohos/AdvancedAPI_OHOS/src/base/bridge/mediaLibraryBase.js b/ohos/AdvancedAPI_OHOS/src/base/bridge/mediaLibraryBase.js new file mode 100644 index 0000000000..5d38313e81 --- /dev/null +++ b/ohos/AdvancedAPI_OHOS/src/base/bridge/mediaLibraryBase.js @@ -0,0 +1,77 @@ +import { context } from './abilityBase' +import abilityAccessCtrl from '@ohos.abilityAccessCtrl' +import photoAccessHelper from '@ohos.file.photoAccessHelper' + +export class MediaLibraryBase { + static getPermissions() { + try { + // 权限列表 + const arrMdl = [ + 'ohos.permission.SHORT_TERM_WRITE_IMAGEVIDEO' + ] + const atManager = abilityAccessCtrl.createAtManager() + return new Promise(resolve => { + atManager.requestPermissionsFromUser(context, arrMdl).then(per => { + const perNum = per.authResults[0] + const dialogShownResults = per.dialogShownResults[0] + resolve({ perNum, dialogShownResults }) + }) + }) + } catch (error) { + console.error('[AdvancedAPI] getPermissions is fail!', JSON.stringify(error)) + } + } + // 获取媒体类型枚举值 + static getMediaType(type) { + return photoAccessHelper.PhotoType[type] + } + + // 获取检索列名枚举值 + static getFileKey() { + return photoAccessHelper.PhotoKeys + } + + // 获取媒体库实例用来访问文件的一系列操作 + static getMedia() { + return photoAccessHelper.getPhotoAccessHelper(context) + } + + // 创建媒体资源 + static async createAsset(media, mediaType, displayName) { + // eslint-disable-next-line camelcase + const media_type = displayName.split('.').pop().toString() + // eslint-disable-next-line camelcase + const media_name = displayName.split('.').shift().toString() + const options = { + title: media_name + } + const uri = await media.createAsset(mediaType, media_type, options) + return uri// Promise + } + + // 关闭媒体库资源文件 + static closeAsset(asset, fd) { + return new Promise(resolve => { + asset.close(fd, (closeErr) => { + if (closeErr !== undefined) { + resolve(false) + } else { + resolve(true) + } + }) + }) + } + + // 获取创建文件的描述符 + static getFd(asset) { + return new Promise(resolve => { + asset.open('rw') + .then((fd) => { + resolve(fd) + }) + .catch(() => { + resolve(false) + }) + }) + } +} diff --git a/ohos/AdvancedAPI_OHOS/src/base/bridge/networkBase.js b/ohos/AdvancedAPI_OHOS/src/base/bridge/networkBase.js new file mode 100644 index 0000000000..b8f75ec35a --- /dev/null +++ b/ohos/AdvancedAPI_OHOS/src/base/bridge/networkBase.js @@ -0,0 +1,27 @@ +/** + * Copyright (c) Huawei Technologies Co., Ltd. 2022-2022. All rights reserved. + * Description: ohos network 模块 + * Author: qianchen + * Create: 06/06/2023 + * Notes: N/A + */ +import network from '@system.network' +export class NetworkBase { + static ohoSubscribe(data) { + const { callback, fail } = data + network.subscribe({ + success: function (data) { + console.log('[QAFAPI] success to subscribe network:' + data.metered + 'type:,' + data.type) + if (callback) { + callback(data) + } + }, + fail: function (err, code) { + console.error('[QAFAPI] fail to subscribe network, code:' + code + ', err:' + err) + if (fail) { + fail(err) + } + } + }) + } +} diff --git a/ohos/AdvancedAPI_OHOS/src/base/bridge/promptBase.js b/ohos/AdvancedAPI_OHOS/src/base/bridge/promptBase.js new file mode 100644 index 0000000000..a370dc5300 --- /dev/null +++ b/ohos/AdvancedAPI_OHOS/src/base/bridge/promptBase.js @@ -0,0 +1,26 @@ +import promptAction from '@ohos.promptAction' +export class PromptBase { + static showToast (params) { + return new Promise((resolve, reject) => { + promptAction.showToast(params) + resolve() + }) + } + + static showDialog (params, callback) { + return new Promise((resolve, reject) => { + promptAction.showDialog(params, callback) + }) + } + + static showActionMenu (params, callback) { + return new Promise((resolve, reject) => { + promptAction.showActionMenu(params, callback) + }) + } + + // 弹框(返回promise) + static ohosShowDialog (params) { + return promptAction.showDialog(params) + } +} diff --git a/ohos/AdvancedAPI_OHOS/src/base/bridge/radioBase.js b/ohos/AdvancedAPI_OHOS/src/base/bridge/radioBase.js new file mode 100644 index 0000000000..fb13fd9cc9 --- /dev/null +++ b/ohos/AdvancedAPI_OHOS/src/base/bridge/radioBase.js @@ -0,0 +1,45 @@ +/** + * Copyright (c) Huawei Technologies Co., Ltd. 2022-2022. All rights reserved. + * Description: ohos radio 模块 + * Author: shenrui + * Create: 04/11/2022 + * Notes: N/A + */ + +import radio from '@ohos.telephony.radio' + +// 网络类型 +export const netWorkConnState = { + UNKNOWN: 0, // 未知网络类型。 + GSM: 1, // 网络类型为GSM(Global System For Mobile Communication)。 + CDMA: 2, // 网络类型为CDMA(Code Division Multiple Access)。 + WCDMA: 3, // 网络类型为WCDMA(Wideband Code Division Multiple Access)。 + TDSCDMA: 4, // 网络类型为TDSCDMA(TimeDivision-Synchronous Code Division Multiple Access)。 + LTE: 5, // 网络类型为LTE(Long Term Evolution)。 + NR: 6 // 网络类型为5G NR(New Radio) +} + +export class RadioBase { + static ohoGetSignalInformation(slotId) { + return new Promise((resolve, reject) => { + radio.getSignalInformation(slotId, (err, data) => { + if (err) { + console.log('[QAFAPI] Failed to get signal information Data. Cause:' + JSON.stringify(err)) + reject(err) + } else { + console.log('[QAFAPI] Success to get signal information Data:' + JSON.stringify(data)) + resolve(data) + } + }) + }) + } + + static ohoIsNrSupported(slotId) { + try { + const result = radio.isNrSupported(slotId) + return result + } catch (err) { + console.error('[QAFAPI] Failed get is supported 5G:' + err) + } + } +} diff --git a/ohos/AdvancedAPI_OHOS/src/base/bridge/securityBase.js b/ohos/AdvancedAPI_OHOS/src/base/bridge/securityBase.js new file mode 100644 index 0000000000..0a8807795f --- /dev/null +++ b/ohos/AdvancedAPI_OHOS/src/base/bridge/securityBase.js @@ -0,0 +1,17 @@ +import cryptoFramework from '@ohos.security.cryptoFramework' +export class SecurityBase { + static rsa(algName, blob) { + return new Promise(async (resolve, reject) => { + let md + try { + md = cryptoFramework.createMd(algName) + await md.update(blob) + const mdOutput = await md.digest() + resolve(mdOutput.data) + } catch (error) { + console.error('[QAFAPI]: rsa fail error code: ' + error.code + ', message is: ' + error.message) + reject(error) + } + }) + } +} diff --git a/ohos/AdvancedAPI_OHOS/src/base/bridge/sensorBase.js b/ohos/AdvancedAPI_OHOS/src/base/bridge/sensorBase.js new file mode 100644 index 0000000000..b53921cec8 --- /dev/null +++ b/ohos/AdvancedAPI_OHOS/src/base/bridge/sensorBase.js @@ -0,0 +1,46 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2022-2022. All rights reserved. + * Description: 封装鸿蒙sensor模块 + * Author: qianyuanyuan + * Create: 3/31/2022 + * Notes: N/A + */ + +import sensor from '@ohos.sensor' + +export class OhosSensorBase { + static ohosSubscribeAccelerometer(data) { + const { interval, callback } = data + sensor.on(sensor.SensorType.SENSOR_TYPE_ID_ACCELEROMETER, (data) => { + callback(data) + }, + { interval: interval } + ) + } + + static ohosUnsubscribeAccelerometer() { + sensor.off(sensor.SensorType.SENSOR_TYPE_ID_ACCELEROMETER) + } + + static ohosSubscribeCompass(data) { + const { callback } = data + sensor.on(sensor.SensorType.SENSOR_TYPE_ID_ORIENTATION, (data) => { + callback(data) + }) + } + + static ohosUnsubscribeCompass() { + sensor.off(sensor.SensorType.SENSOR_TYPE_ID_ORIENTATION) + } + + static ohosSubscribeGyroscope(object) { + const { intervalValue, callback } = object + sensor.on(sensor.SensorId.GYROSCOPE, (data) => { + callback(data) + }, { interval: intervalValue }) + } + + static ohosUnsubscribeGyroscope() { + sensor.off(sensor.SensorId.GYROSCOPE) + } +} diff --git a/ohos/AdvancedAPI_OHOS/src/base/bridge/wantConstantBase.js b/ohos/AdvancedAPI_OHOS/src/base/bridge/wantConstantBase.js new file mode 100644 index 0000000000..ddb5f2e840 --- /dev/null +++ b/ohos/AdvancedAPI_OHOS/src/base/bridge/wantConstantBase.js @@ -0,0 +1,6 @@ +import wantConstant from '@ohos.ability.wantConstant' +export class WantConstantBase { + static getAction(type) { + return wantConstant.Action[type] + } +} diff --git a/ohos/AdvancedAPI_OHOS/src/base/bridge/wifiBase.js b/ohos/AdvancedAPI_OHOS/src/base/bridge/wifiBase.js new file mode 100644 index 0000000000..57ce3bd8af --- /dev/null +++ b/ohos/AdvancedAPI_OHOS/src/base/bridge/wifiBase.js @@ -0,0 +1,69 @@ +/** + * Copyright (c) Huawei Technologies Co., Ltd. 2022-2022. All rights reserved. + * Description: ohos wifi 模块 + * Author: qianchen + * Create: 04/11/2022 + * Notes: + */ + +import wifi from '@ohos.wifi' +export class WifiBase { + static ConnState = { + SCANNING: 0, // 设备正在搜索可用的AP + CONNECTING: 1, // 设备正在搜索可用的AP。 + AUTHENTICATING: 2, // WLAN连接正在认证中 + OBTAINING_IPADDR: 3, // 正在获取WLAN连接的IP地址 + CONNECTED: 4, // WLAN连接已建立 + DISCONNECTING: 5, // WLAN连接正在断开 + DISCONNECTED: 6, // WLAN连接已断开 + UNKNOWN: 7// WLAN连接建立失败 + } + static isWifiActive () { + return wifi.isWifiActive() + } + + static scan () { + return wifi.scan() + } + static ohoGetLinkedInfo() { + return new Promise((resolve, reject) => { + wifi.getLinkedInfo((err, data) => { + if (err) { + console.log('[QAFAPI] get linked info error:' + err) + reject(err) + } else { + console.log('[QAFAPI] get wifi linked info: ' + JSON.stringify(data)) + resolve(data) + } + }) + }) + } + static connectionChange (cb) { + wifi.on('wifiConnectionChange', cb) + } + + static StateType = { + OFF: 0, + ON: 1 + } + + static scanStateChange (cb) { + wifi.on('wifiScanStateChange', cb) + } + + static ScanState = { + SUCCESS: 1, + FAIL: 0 + } + + static getScanInfos () { + return new Promise((resolve, reject) => { + wifi.getScanInfos().then(scanResult => { + resolve(scanResult) + }).catch(error => { + console.info('[QAFAPI] getScanInfos error ' + JSON.stringify(error)) + reject(error) + }) + }) + } +} diff --git a/ohos/AdvancedAPI_OHOS/src/base/bridge/windowBase.js b/ohos/AdvancedAPI_OHOS/src/base/bridge/windowBase.js new file mode 100644 index 0000000000..d65f334a49 --- /dev/null +++ b/ohos/AdvancedAPI_OHOS/src/base/bridge/windowBase.js @@ -0,0 +1,64 @@ +import oWindow from '@ohos.window' + +export const TYPE_SYSTEM = 1 // 表示系统窗口 + +function getWinDisplay(ctx) { + return new Promise(res => { + if (globalThis.isStageModel) { + oWindow.getLastWindow(ctx, (err, data) => { + if (err.code) { + console.error('[QAFAPI] Failed to obtain the top window. Cause: ' + JSON.stringify(err)) + } else { + res(data) + } + }) + } else { + oWindow.getLastWindow((err, data) => { + if (err.code) { + console.error('[QAFAPI] Failed to obtain the top window. Cause: ' + JSON.stringify(err)) + } else { + res(data) + } + }) + } + }) +} + +export class AsyncWindowBase { + static async getWindow (ctx) { + const windowClass1 = await getWinDisplay(ctx) + return new Promise(res => { + windowClass1.getProperties().then((data) => { + if (data.type === TYPE_SYSTEM) { + res(data.windowRect) + } + }).catch((err) => { + console.error('[QAFAPI] window.getProperties Failed to obtain the area. Cause:' + JSON.stringify(err)) + }) + }) + } + static async getCutout (ctx) { + const windowClass2 = await getWinDisplay(ctx) + return new Promise(res => { + windowClass2.getAvoidArea(oWindow.AvoidAreaType.TYPE_CUTOUT, (errs, data) => { + if (errs.code) { + console.error('[QAFAPI] window Failed to obtain the area. Cause:' + JSON.stringify(errs)) + } else { + res(data) + } + }) + }) + } + static async getSystemCutout (ctx) { + const windowClass2 = await getWinDisplay(ctx) + return new Promise(res => { + windowClass2.getAvoidArea(oWindow.AvoidAreaType.TYPE_SYSTEM, (errs, data) => { + if (errs.code) { + console.error('[QAFAPI] window Failed to obtain the area. Cause:' + JSON.stringify(errs)) + } else { + res(data) + } + }) + }) + } +} diff --git a/ohos/AdvancedAPI_OHOS/src/base/decorators/index.js b/ohos/AdvancedAPI_OHOS/src/base/decorators/index.js new file mode 100644 index 0000000000..8716eb851a --- /dev/null +++ b/ohos/AdvancedAPI_OHOS/src/base/decorators/index.js @@ -0,0 +1,29 @@ +export function jsMethod (desc) { + return (target, key, descriptor) => { + let _jsMethods + // common 代表 方法为通用方法,所有模块共用 + if (desc && desc.common) { + _jsMethods = target.constructor._jsBaseMethods = target.constructor._jsBaseMethods || {} + } else { + _jsMethods = target.constructor._jsMethods = target.constructor._jsMethods || {} + } + desc = desc !== undefined ? desc : {} + const alias = desc.alias !== undefined ? desc.alias : key + const callback = desc.callback !== undefined ? desc.callback : true + const methodName = key + _jsMethods[alias] = { methodName, callback } + } +} + +export function jsField (desc) { + const PREFIX = '__FIELD__' + return (target, key, descriptor) => { + const _jsModuleAttrs = target.constructor._jsModuleAttrs = target.constructor._jsModuleAttrs || [] + desc = desc !== undefined ? desc : {} + const alias = desc.alias !== undefined ? desc.alias : key + const callback = desc.callback !== undefined ? desc.callback : true + const getMetName = desc.getMetName + const setMetName = desc.setMetName + _jsModuleAttrs[PREFIX + alias] = { getMetName, setMetName, callback } + } +} diff --git a/ohos/AdvancedAPI_OHOS/src/base/module/Bluetooth/BluetoothBaseErrorCode.js b/ohos/AdvancedAPI_OHOS/src/base/module/Bluetooth/BluetoothBaseErrorCode.js new file mode 100644 index 0000000000..bd338a7bf8 --- /dev/null +++ b/ohos/AdvancedAPI_OHOS/src/base/module/Bluetooth/BluetoothBaseErrorCode.js @@ -0,0 +1,44 @@ +/** + * Copyright (c) Huawei Technologies Co., Ltd. 2022-2022. All rights reserved. + * Description: 蓝牙模块错误码 + * Author: wangtianpeng + * Create: 04/26/2022 + */ + +export const BLHErrorCode = { + // 正常 + OK: 0, + + // 未启动连接 + NOT_INIT: 10000, + + // 当前蓝牙适配器不可用 + NOT_AVAILABLE: 10001, + + // 没有找到指定设备 + NO_DEVICE: 10002, + + // 连接失败 + CONNECTION_FAIL: 10003, + + // 没有找到指定服务 + NO_SERVICE: 10004, + + // 没有找到指定服务 + NO_CHARACTERISTIC: 10005, + + // 当前连接已断开 + NO_CONNECTION: 10006, + + // 当前特征值不支持此操作 + PROPERTY_NO_SUPPORT: 10007, + + // 当前特征值不支持此操作 + SYSTEM_ERROR: 10008, + + // 系统版本低于 5.0 不支持 BLE + SYSTRM_NOT_SUPPORT: 10009, + + // 入参不正确 + INVALID_PARAM: 202 +} diff --git a/ohos/AdvancedAPI_OHOS/src/base/module/Bluetooth/BluetoothBaseModule.js b/ohos/AdvancedAPI_OHOS/src/base/module/Bluetooth/BluetoothBaseModule.js new file mode 100644 index 0000000000..290910ae92 --- /dev/null +++ b/ohos/AdvancedAPI_OHOS/src/base/module/Bluetooth/BluetoothBaseModule.js @@ -0,0 +1,960 @@ +// 蓝牙开启状态 +import { jsMethod } from '../../decorators' +import { BluetoothBase } from '../../bridge/bluetoothBase' +import { BLHErrorCode, ErrorCode } from '../../util/ErrorCode' +import { isArray, isString, isArrayBuffer, isBoolean, isLower, isMac, isNumber, isUuid } from '../../util/checkDataType' +import { PromptBase } from '../../bridge/promptBase' + +export const BLESTATE = { + STATE_ON: 2, // 蓝牙已开启 + STATE_OFF: 0, // 蓝牙已关闭 + INDEX: 1, // 对话框允许按钮 + STATE_CONNECTED: 2, // 表示profile已连接 + STATE_DISCONNECTED: 0 // 表示profile已断连 +} + +// 默认值 +export const DEFAULT = { + OPEN: false, // 默认拒绝弹窗开启蓝牙 + OPEN_MSG: '快应用加载器想要开启蓝牙', + CLOSE_MSG: '快应用加载器请求关闭蓝牙', + ALLOW_BUTTON: '允许', + REFUSE_BUTTON: '拒绝' +} + +export class BluetoothBaseModule { + constructor() { + // 监听蓝牙适配器状态变化 + this.onadapterstatechange + + // 监听寻找到新设备的事件 + this.ondevicefound + + // 默认值为false。是否允许重复上报同一设备。如果允许重复上报,则bluetooth.ondevicefound 方法会多次上报同一设备,但是RSSI值会有不同。 + this.allowDuplicatesKey = false + + // 设备上报间隔 + this.interval = 0 + // 适配器状态 + this.state = { + available: BluetoothBase.bluetoothState() === BLESTATE.STATE_ON, // 蓝牙开启状态 + discovering: false // 是否处于扫描模式 cp执行开始扫描or停止函数时修改此变量 + } + // 存储成功连接ble设备的deviceId + this.deviceIdBle + + // 蓝牙开启期间扫描到的全部设备 + this.scanResult = [] + + // clent实例 + this.gattClient = null + // 扫描监听模式(true:低功耗,false:蓝牙) + this.isOnBle = { mode: false } + // 低功耗蓝牙连接状态 + this.stateBLE = {} + this.services = [] + this.bleCharacteristic = {} + this.characteristicValue = null + // uniapp需要初始化蓝牙,与快应用不一致 + this.isInit = false + + this.devicesFoundListeners = [] + this.adapterStateChangeListeners = [] + + this.BLEConnectionStateListeners = [] + this.BLECharacteristicListeners = [] + } + // 1.打开蓝牙 + @jsMethod({ alias: 'openAdapter', common: false, callback: true }) + openAdapter(object) { + const { operateAdapter = DEFAULT.OPEN } = object || {} // object默认值防止没传参 + const bluetoothState = BluetoothBase.bluetoothState() === BLESTATE.STATE_ON // 获取当前设备蓝牙状态 + return new Promise((resolve, reject) => { + if (bluetoothState) { + resolve([['bluetooth is turned']]) // 当前蓝牙为打开状态时走success + } else { // 蓝牙未开启状态 + if (operateAdapter) { // 是否弹框显示允许/拒绝 + this.promptTemp(DEFAULT.OPEN_MSG) + .then(data => { + if (data.index === BLESTATE.INDEX) { // 选中允许按钮 + BluetoothBase.enableBluetooth() && resolve([[BLHErrorCode.OK]]) // 打开蓝牙返回0 + this.state.available = true // 修改全局监听对象 + } else { + reject([['user reject', BLHErrorCode.SYSTEM_ERROR]]) // 选中拒绝按钮返回fail + } + }) + } else { + reject([['not available', BLHErrorCode.NOT_AVAILABLE]]) // 拒绝弹框or未传参提示走fail + } + } + }) + } + + // 2.关闭蓝牙 + @jsMethod({ alias: 'closeAdapter', common: false, callback: true }) + closeAdapter(object) { + const { operateAdapter = DEFAULT.OPEN } = object || {} // object默认值防止没传参 + const bluetoothState = BluetoothBase.bluetoothState() === BLESTATE.STATE_OFF // 获取当前设备蓝牙关闭状态 + return new Promise((resolve, reject) => { + if (bluetoothState) { + reject([['bluetooth is not turned', BLHErrorCode.NOT_INIT]]) // 当前蓝牙为关闭状态时走fail + } else { + if (operateAdapter) { + // 快应用拒绝时不会有任何调用 + this.promptTemp(DEFAULT.CLOSE_MSG) + .then(data => { + if (data.index === BLESTATE.INDEX) { // 选中允许按钮 + BluetoothBase.disableBluetooth() && resolve([[BLHErrorCode.OK]]) // 关闭蓝牙返回0 + this.state.available = false // 修改全局监听对象 + try { + BluetoothBase.offBLE() + } catch (err) { + console.error(`[QAFAPI] OpenHarmony Error ondevicefound,error Message:${err}`) + } + } + }) + } else { + resolve([['closeBluetoothAdapter success']]) // 并不能真正关闭蓝牙仅走成功回调(快应用逻辑问题) + } + } + }) + } + + // 3.获取本机蓝牙适配器状态 + @jsMethod({ alias: 'getAdapterState', common: false, callback: true }) + getAdapterState() { + const bluetoothState = BluetoothBase.bluetoothState() === BLESTATE.STATE_ON // 获取当前设备蓝牙开启状态 + return new Promise((resolve) => { + resolve({ + discovering: this.state.discovering, + available: bluetoothState + }) + }) + } + + // 5.开始搜寻附近的蓝牙外围设备(参数只校验不处理) + @jsMethod({ alias: 'startDevicesDiscovery', common: false, callback: true }) + startDevicesDiscovery(object) { + const bluetoothState = BluetoothBase.bluetoothState() === BLESTATE.STATE_ON // 获取当前设备蓝牙状态 + return new Promise((resolve, reject) => { + // 校验当前蓝牙状态 + if (!bluetoothState) { + reject([['bluetooth is not turned', BLHErrorCode.NOT_AVAILABLE]]) + return + } + + // 传参校验 + if (object) { + const { services, allowDuplicatesKey, interval } = object + if ( + (services && !isArray(services)) + || (allowDuplicatesKey && !isBoolean(allowDuplicatesKey)) + || (interval && !isNumber(interval))) { + reject([['invalidParam', BLHErrorCode.SYSTEM_ERROR]]) + return + } + + // services内部uuid校验 + let filters = [] + if (services) { + const isAllPass = services.every(serviceUuid => { + filters.push({ serviceUuid }) + return isUuid(serviceUuid.toLowerCase()) + }) + if (!isAllPass) { + reject([['uuid invalid', BLHErrorCode.NO_DEVICE]]) + return + } + + // 监听模式开关,当传入正确services时执行低功耗监听 + this.isOnBle.mode = true + } else { + filters = null + } + + // 调整全局重复上报参数 + if (allowDuplicatesKey) { + this.allowDuplicatesKey = allowDuplicatesKey + } + + // 调整全局上报设备间隔 + if (interval) { + this.interval = interval + } + } + + // 启动蓝牙扫描(蓝牙扫描兼容低功耗扫描) + BluetoothBase.startBLEScan(this.interval) + const isScanOpen = BluetoothBase.startBluetoothDiscovery() + + if (isScanOpen) { + this.state.discovering = true // 适配器扫描状态开启 + resolve('ok') + } else { + reject([[`[QAFAPI] openHarmony startBluetoothDiscovery fail`, BLHErrorCode.CONNECTION_FAIL]]) + } + }) + } + + // 6.停止搜寻附近的蓝牙外围设备 + @jsMethod({ alias: 'stopDevicesDiscovery', common: false, callback: true }) + stopDevicesDiscovery() { + return new Promise((resolve, reject) => { + // 仅有状态为0时认定为蓝牙处于关闭 + if (BluetoothBase.bluetoothState()) { + BluetoothBase.stopBLEScan() + const isScanClose = BluetoothBase.stopBluetoothDiscovery() + // 适配器扫描状态关闭 + this.state.discovering = false + if (isScanClose) { + resolve('ok') + this.devicesFoundListeners = [] + // 重置监听模式开关 + this.isOnBle.mode = false + + // 重置上报间隔 + this.interval = 0 + + // 重置重复上报 + this.allowDuplicatesKey = false + } else { + resolve('ok') + } + } else { + reject(['bluetooth is not turned', BLHErrorCode.NOT_AVAILABLE]) + } + }) + } + + // 7.获取在蓝牙模块生效期间所有已发现的蓝牙设备(依赖startDevicesDiscovery&&ondevicefound执行) + @jsMethod({ alias: 'getDevices', common: false, callback: true }) + getDevices() { + const bluetoothState = BluetoothBase.bluetoothState() === BLESTATE.STATE_ON // 获取当前设备蓝牙状态 + return new Promise((resolve, reject) => { + if (bluetoothState) { + resolve([[{ devices: this.scanResult }]]) + } else { + reject([['bluetooth is not turned', BLHErrorCode.NOT_AVAILABLE]]) // 快应用无法测试到扫描关闭的情况 + } + }) + } + + saveDevice(resultObj) { + // 是否允许重复值(默认不重复) + if (this.allowDuplicatesKey) { + this.scanResult.push(resultObj) + } else { + if (!this.isRepeat(this.scanResult, resultObj.deviceId)) { + this.scanResult.push(resultObj) + } + } + } + + onFoundEvent(device) { + const resultObj = this.getTemp() + if (device[0] && device[0].deviceId) { + // 返回值 [{"deviceId":""XX:XX:XX:XX:XX:XX"","rssi":-71,"data":{}}] + const { deviceId, rssi, data } = device[0] + resultObj.deviceId = deviceId + resultObj.RSSI = rssi + resultObj.serviceData = data + try { + const GattClient = BluetoothBase.createGattClientDevice(deviceId) + GattClient.connect() + GattClient.getDeviceName((_, data) => { + resultObj.name = data + resultObj.localName = data + try { + GattClient.disconnect() + // 关闭临时客户端 + GattClient.close() + } catch (err) { + console.warn(`[QAFAPI] close client fail: ${JSON.stringify(err)}`) + } + this.saveDevice(resultObj) + }) + } catch (err) { + console.warn(`[QAFAPI] close client fail: ${JSON.stringify(err)}`) + } + } else { + // 返回值 ["XX:XX:XX:XX:XX:XX"] + resultObj.deviceId = device[0] + resultObj.name = BluetoothBase.getRemoteDeviceName(resultObj.deviceId) + resultObj.localName = resultObj.name + console.debug('[QAFAPI] onFoundEvent:' + JSON.stringify(resultObj)) + this.saveDevice(resultObj) + } + } + + // 9.根据 uuid 获取处于已连接状态的设备 + @jsMethod({ alias: 'getConnectedDevices', common: false, callback: true }) + getConnectedDevices(object) { + return new Promise((resolve, reject) => { + // 获取当前设备蓝牙状态 + const bluetoothState = BluetoothBase.bluetoothState() === BLESTATE.STATE_ON + if (!bluetoothState) { + reject([['bluetooth is not turned', BLHErrorCode.NOT_AVAILABLE]]) + return + } + if (!object || !object.services || !isArray(object.services) || object.services.length === 0) { + reject([['invalidParam', BLHErrorCode.SYSTEM_ERROR]]) + return + } + console.debug('[QAFAPI] services : ' + JSON.stringify(object.services)) + // 参数校验(uuid) + const isRightServices = object.services.every(item => { + return isUuid(item.toLowerCase()) + }) || false + if (!object || !isRightServices) { + console.debug('[QAFAPI] invalidParam services ') + reject([['invalidParam', BLHErrorCode.SYSTEM_ERROR]]) + return + } + // 获取连接的低功耗设备(接口有问题不能正确返回) + let deviceIds = [] + try { + deviceIds = BluetoothBase.getConnectedBLEDevices() + } catch (err) { + console.error('[QAFAPI] errCode:' + err.code + ',errMessage:' + err.message) + } + console.debug('[QAFAPI] BleDeviceIds = ' + JSON.stringify(deviceIds)) + + // 0x0001 表示A2DP;0x0004 表示HFP, 0x0006 表示HID, 0x0007 表示PAN + const profileId = [0x0001, 0x0004, 0x0006, 0x0007] + + // 获取getProfile实例 + try { + // getProfile接口api9会导致闪退 + profileId.forEach(item => { + const profiles = BluetoothBase.getProfile(item) + console.error('[QAFAPI] profiles' + JSON.stringify(profiles)) + if (profiles) { + deviceIds = [...deviceIds, ...profiles] + } + }) + } catch (err) { + console.error('[QAFAPI] getProfile fail' + err) + } + + // 获取信息去重 + deviceIds = deviceIds.reduce((pr, cu) => pr.includes(cu) ? pr : [...pr, cu], []) + + // 未连接任何低功耗设备 + if (!deviceIds || deviceIds.length === 0) { + reject([['no device', BLHErrorCode.NO_DEVICE]]) + return + } + + // 获取设备名 + const devices = [] + deviceIds.forEach(item => { + devices.push({ + // 成功获取名字依赖扫描获取到该设备 + name: BluetoothBase.getRemoteDeviceName(item), + deviceId: item + }) + }) + resolve([[{ devices }]]) + }) + } + + BLECharacteristicCallback = (valueChange) => { + console.debug('[AdvancedAPI] characteristicChange triger valueChange:' + JSON.stringify(valueChange)) + const { serviceUuid, characteristicUuid } = valueChange + const characteristicValue = new Uint8Array( + valueChange.characteristicValue + ) + const notification = { + deviceId: this.deviceIdBle, + serviceId: serviceUuid, + characteristicId: characteristicUuid, + value: characteristicValue, + } + // 遍历所有的监听者 + for (const listener of this.BLECharacteristicListeners) { + listener(notification) + } + } + + // 10.连接低功耗蓝牙设备 + @jsMethod({ alias: 'createBLEConnection', common: false, callback: true }) + createBLEConnection(object) { + const { deviceId, timeout } = object || {} + + return new Promise((resolve, reject) => { + const bluetoothState = BluetoothBase.bluetoothState() === BLESTATE.STATE_ON // 获取当前设备蓝牙状态 + if (!bluetoothState) { + reject([['bluetooth is not turned', BLHErrorCode.NOT_AVAILABLE]]) + return + } + if (timeout && !isNumber(timeout)) { + reject([['invalidParam', BLHErrorCode.SYSTEM_ERROR]]) + return + } + if (!deviceId || !isString(deviceId)) { + reject([['invalidParam', BLHErrorCode.SYSTEM_ERROR]]) + } else { + this.gattClient = BluetoothBase.createGattClientDevice(deviceId) + // 开启监听该设备的连接状态 + this.gattClient.on('BLEConnectionStateChange', state => { + const temp = (state.state === 2) + if (this.stateBLE[state.deviceId] !== temp) { + this.stateBLE[state.deviceId] = temp + } + }) + try { + this.gattClient.on('BLECharacteristicChange', this.BLECharacteristicCallback) + console.debug('[AdvancedAPI] BLECharacteristicChange Registration succeeded.') + } catch (err) { + console.error(`AdvancedAPI BLECharacteristicChange Registration fail ${err.message}`) + } + + // 创建实例 + const successConnect = this.gattClient.connect() + + // 延时上报 + if (timeout) { + setTimeout(() => { + if (successConnect) { + resolve('ok') + this.deviceIdBle = deviceId + } else { + reject([['connection timed out', BLHErrorCode.CONNECTION_FAIL]]) + } + }, timeout) + } else { + if (!successConnect) { + reject([['fail connection', BLHErrorCode.CONNECTION_FAIL]]) + return + } + resolve('ok') + this.deviceIdBle = deviceId + } + } + }) + } + + // 11.断开与低功耗蓝牙设备的连接(接口问题无法完成关闭会走fail回调) + @jsMethod({ alias: 'closeBLEConnection', common: false, callback: true }) + closeBLEConnection(object) { + const { deviceId } = object || {} + return new Promise((resolve, reject) => { + if (!deviceId || !isString(deviceId)) { + reject([['Deviceid must be written', BLHErrorCode.SYSTEM_ERROR]]) + return + } + try { + this.gattClient.disconnect() + this.gattClient.close() + this.gattClient = null + this.stateBLE[deviceId] = false + resolve('ok') + } catch (err) { + reject([['Failed to disconnect the Bluetooth connection', BLHErrorCode.SYSTEM_ERROR]]) + return + } + }) + } + + // 12.获取蓝牙设备所有服务(service) + @jsMethod({ alias: 'getBLEDeviceServices', common: false, callback: true }) + getBLEDeviceServices(object) { + const { deviceId } = object || {} + return new Promise((resolve, reject) => { + // 未传入deviceId参数 + if (!deviceId || !isString(deviceId)) { + reject([['invalidParam', BLHErrorCode.SYSTEM_ERROR]]) + return + } + + // 传入deviceID格式错误 + if (!isMac(deviceId)) { + reject([['deviceId is not MAC', BLHErrorCode.SYSTEM_ERROR]]) + return + } + + // 获取当前设备蓝牙状态 + const bluetoothState = BluetoothBase.bluetoothState() === BLESTATE.STATE_ON + if (!bluetoothState) { + reject([['bluetooth is not turned', BLHErrorCode.NOT_AVAILABLE]]) + return + } + console.debug('[QAFAPI] getServices deviceId:' + deviceId + ' this.deviceIdBLE = ' + this.deviceIdBle) + // 获取实例 + let gattClient + if (this.gattClient && deviceId === this.deviceIdBle) { + console.debug('[QAFAPI] getServices deviceId:' + deviceId) + gattClient = this.gattClient + } else { + gattClient = BluetoothBase.createGattClientDevice(deviceId) + gattClient.connect() + this.gattClient = gattClient + this.deviceIdBle = deviceId + } + // 获取所有服务 + gattClient.getServices().then(res => { + const arr = [] + res.forEach(item => { + console.debug('[QAFAPI] getServices services = ' + JSON.stringify(item)) + const { serviceUuid, isPrimary } = item + const temp = { + uuid: serviceUuid, + isPrimary + } + arr.push(temp) + }) + this.services = res + resolve([[{ 'services': arr }]]) + }).catch((err) => { + console.error('[QAFAPI] getServices fail:' + JSON.stringify(err)) + resolve([[{ 'services': [] }]]) + }) + }) + } + + // 13.获取蓝牙设备某个服务中所有特征值(暂不支持) + @jsMethod({ alias: 'getBLEDeviceCharacteristics', common: false, callback: true }) + getBLEDeviceCharacteristics(object) { + return new Promise((resolve, reject) => { + // 参数校验 + if (!object) { + reject([['invalidParam', BLHErrorCode.SYSTEM_ERROR]]) + return + } + const { deviceId, serviceId } = object + console.info('[QAFAPI] getBLEDeviceCharacteristics deviceId:' + deviceId + ' serviceId = ' + serviceId) + if (!deviceId || !isString(deviceId) || !serviceId || !isString(serviceId)) { + reject([['invalidParam', BLHErrorCode.SYSTEM_ERROR]]) + return + } + + // 获取实例 + console.info('[QAFAPI] getBLEDeviceCharacteristics deviceId:' + deviceId + ' this.deviceIdBLE = ' + this.deviceIdBle) + let gattClient + if (this.gattClient && deviceId === this.deviceIdBle) { + console.info('[QAFAPI] getBLEDeviceCharacteristics deviceId:' + deviceId) + gattClient = this.gattClient + } else { + gattClient = BluetoothBase.createGattClientDevice(deviceId) + gattClient.connect() + this.gattClient = gattClient + this.deviceIdBle = deviceId + } + + // 获取所有服务 + gattClient.getServices().then(res => { + // 已获取的服务列表对象 + let Servicesfound + + // 遍历从所有服务中找到对应serviceId服务的特征值 + this.services.forEach((item) => { + console.info('[QAFAPI] serviceId = ' + JSON.stringify(item)) + if (item.serviceUuid === serviceId) { + Servicesfound = item + } + }) + + // 未获取到特征值 + if (!Servicesfound) { + reject([['Service not found', BLHErrorCode.NO_SERVICE]]) + return + } + + // 获取特征需要返回的字段对象 + const characteristics = [] + this.bleDescriptor = Servicesfound + Servicesfound.characteristics.forEach(item => { + console.info('[QAFAPI] Servicesfound item = ' + JSON.stringify(item)) + characteristics.push({ + uuid: item.characteristicUuid, + properties: item.properties + }) + }) + + // 找不到返回空数组 + resolve([[{ characteristics }]]) + }).catch(err => { + console.error(`[QAFAPI] OpenHarmony Error getServices value,error Message:${err}`) + reject([['property not support', BLHErrorCode.PROPERTY_NOT_SUPPORT]]) + }) + }) + } + + // 14.读取低功耗蓝牙设备的特征值的二进制数据值(暂不支持) + @jsMethod({ alias: 'readBLECharacteristicValue', common: false, callback: true }) + readBLECharacteristicValue(object) { + return new Promise((resolve, reject) => { + // 参数校验 + if (!object) { + reject([['invalidParam', BLHErrorCode.SYSTEM_ERROR]]) + return + } + const { deviceId, serviceId, characteristicId } = object + if (!isString(deviceId) || !isString(serviceId) || !isString(characteristicId)) { + reject([['invalidParam', BLHErrorCode.SYSTEM_ERROR]]) + return + } + if ( + !deviceId + || !serviceId + || !isUuid(serviceId.toLowerCase()) + || !characteristicId + || !isUuid(characteristicId.toLowerCase()) + ) { + reject([['invalidParam', BLHErrorCode.SYSTEM_ERROR]]) + return + } + if (!isMac(deviceId.toLowerCase())) { + reject([['deviceId is not MAC', BLHErrorCode.SYSTEM_ERROR]]) + return + } + this.queryBLECharacteristic(deviceId, serviceId).then(desc => { + const descriptors = [] + const descriptor = { + serviceUuid: serviceId.toLowerCase(), + characteristicUuid: characteristicId.toLowerCase(), + descriptorUuid: desc.descriptorUuid, + descriptorValue: desc.descriptorValue, + } + descriptors.push(descriptor) + + const characteristicIn = { + serviceUuid: serviceId.toLowerCase(), + characteristicUuid: characteristicId.toLowerCase(), + characteristicValue: this.characteristicValue, + descriptors: descriptors, + } + console.debug('[QAFAPI] characteristicIn = ' + JSON.stringify(characteristicIn)) + // 向服务端发送设置通知此特征值请求notify + let GattClient = null + let result + if (this.gattClient && this.deviceIdBle === deviceId) { + try { + result = this.gattClient.readCharacteristicValue(characteristicIn) + } catch (err) { + reject([[err.message, ErrorCode.PARAMETER_ERROR]]) + console.error('[QAFAPI]readBLECharacteristicValue errCode:' + err.code + ',errMessage:' + err.message) + } + } else { + try { + GattClient = BluetoothBase.createGattClientDevice(deviceId) + result = GattClient.readCharacteristicValue(characteristicIn) + } catch (err) { + reject([[err.message, ErrorCode.PARAMETER_ERROR]]) + console.error('[QAFAPI]readBLECharacteristicValue errCode:' + err.code + ',errMessage:' + err.message) + } + } + // 缺少低功耗设备未连接状态的失败回调(暂不支持直接获取) + if (result) { + result.then((BLECharacteristic) => { + resolve([BLECharacteristic]) + }).catch((err) => { + console.error('[AdvancedAPI] Failed to read characteristic value' + err.message) + reject([['property not support', BLHErrorCode.PROPERTY_NOT_SUPPORT]]) + }) + } else { + reject([['property not support', BLHErrorCode.PROPERTY_NOT_SUPPORT]]) + } + }).catch(_ => { + reject([['Bluetooth not available', BLHErrorCode.SYSTEM_ERROR]]) + }) + }) + } + + // 15.向低功耗蓝牙设备特征值中写入二进制数据(暂不支持) + @jsMethod({ alias: 'writeBLECharacteristicValue', common: false, callback: true }) + writeBLECharacteristicValue(object) { + return new Promise((resolve, reject) => { + // 参数校验 + if (!object) { + reject([['invalidParam', BLHErrorCode.SYSTEM_ERROR]]) + return + } + + const { deviceId, serviceId, characteristicId, value } = object + if (!isString(deviceId) || !isString(serviceId) || !isString(characteristicId) || !isArrayBuffer(value) || !isMac(deviceId)) { + reject([['invalidParam', BLHErrorCode.SYSTEM_ERROR]]) + return + } + if ( + !deviceId + || !serviceId + || !isUuid(serviceId.toLowerCase()) + || !characteristicId + || !isUuid(characteristicId.toLowerCase()) + || !isLower(characteristicId.toLowerCase()) + || !value + ) { + reject([['invalidParam', BLHErrorCode.SYSTEM_ERROR]]) + return + } + + this.queryBLECharacteristic(deviceId, serviceId).then(desc => { + const descriptors = [] + const descriptor = { + serviceUuid: serviceId.toLowerCase(), + characteristicUuid: characteristicId.toLowerCase(), + descriptorUuid: desc.descriptorUuid, + descriptorValue: desc.descriptorValue, + } + descriptors.push(descriptor) + + const characteristicIn = { + serviceUuid: serviceId.toLowerCase(), + characteristicUuid: characteristicId.toLowerCase(), + characteristicValue: value, + descriptors: descriptors, + } + console.debug('[QAFAPI] characteristicIn = ' + JSON.stringify(characteristicIn)) + let GattClient = null + let isWrite + if (this.gattClient && this.deviceIdBle === deviceId) { + try { + isWrite = this.gattClient.writeCharacteristicValue(characteristicIn) + } catch (err) { + reject([[err.message, ErrorCode.PARAMETER_ERROR]]) + console.error('[QAFAPI]writeCharacteristicValue errCode:' + err.code + ',errMessage:' + err.message) + } + } else { + try { + GattClient = BluetoothBase.createGattClientDevice(deviceId) + isWrite = GattClient.writeCharacteristicValue(characteristicIn) + } catch (err) { + reject([[err.message, ErrorCode.PARAMETER_ERROR]]) + console.error('[QAFAPI]readBLECharacteristicValue errCode:' + err.code + ',errMessage:' + err.message) + } + } + // 缺少低功耗设备未连接状态的失败回调(暂不支持直接获取) + if (isWrite) { + resolve('ok') // 写入成功 + } else { + reject([['property not support', BLHErrorCode.PROPERTY_NOT_SUPPORT]]) // 写入失败 + } + }).catch(_ => { + reject([['Bluetooth not available', BLHErrorCode.SYSTEM_ERROR]]) + }) + }) + } + + queryBLECharacteristic(deviceId, serviceId) { + return new Promise((resolve, reject) => { + if (this.descriptors && deviceId.toLowerCase() === this.deviceIdBle.toLowerCase()) { + resolve(this.descriptors) + return + } + let gattClient + if (this.gattClient && deviceId.toLowerCase() === this.deviceIdBle.toLowerCase()) { + console.info('[QAFAPI] queryBLECharacteristic deviceId:' + deviceId) + gattClient = this.gattClient + } else { + gattClient = BluetoothBase.createGattClientDevice(deviceId) + gattClient.connect() + this.gattClient = gattClient + this.deviceIdBle = deviceId + } + + // 获取所有服务 + gattClient.getServices().then((res) => { + // 已获取的服务列表对象 + let Servicesfound + + // 遍历从所有服务中找到对应serviceId服务的特征值 + res.forEach((item) => { + if (item.serviceUuid.toLowerCase() === serviceId.toLowerCase()) { + Servicesfound = item + } + }) + + // 未获取到特征值 + if (!Servicesfound) { + reject([['Service not found', BLHErrorCode.NO_SERVICE]]) + return + } + + // 获取特征需要返回的字段对象 + const characteristics = Servicesfound.characteristics + characteristics.forEach((item) => { + if (item.serviceUuid.toLowerCase() === serviceId.toLowerCase()) { + this.characteristicValue = item.characteristicValue + item.descriptors.forEach((descriptor) => { + if (descriptor.serviceUuid.toLowerCase() === serviceId.toLowerCase()) { + this.descriptors = descriptor + console.info('[QAFAPI] Servicesfound descriptor = ' + JSON.stringify(descriptor)) + resolve(this.descriptors) + } else { + reject([['characteristics not found', BLHErrorCode.NO_SERVICE]]) + } + }) + } else { + console.error(`[AdvancedAPI] characteristics not found`) + reject([['characteristics not found', BLHErrorCode.NO_SERVICE]]) + } + }) + }).catch(err => { + console.error(`[AdvancedAPI] getServices fail:${err.message}`) + reject([['Service not found', BLHErrorCode.NO_SERVICE]]) + }) + }) + } + + // 16.启用低功耗蓝牙设备特征值变化时的notify功能(暂不支持) + @jsMethod({ alias: 'notifyBLECharacteristicValueChange', common: false, callback: true }) + notifyBLECharacteristicValueChange(object) { + return new Promise((resolve, reject) => { + // 参数校验 + if (!object) { + reject([['invalidParam', BLHErrorCode.SYSTEM_ERROR]]) + return + } + const { deviceId, serviceId, characteristicId, state } = object + if ( + !deviceId || !isString(deviceId) + || !serviceId || !isString(serviceId) + || !isUuid(serviceId.toLowerCase()) + || !characteristicId || !isString(characteristicId) + || !isUuid(characteristicId.toLowerCase()) + || !state || !isBoolean(state) + ) { + reject([['invalidParam', BLHErrorCode.SYSTEM_ERROR]]) + return + } + if (!isMac(deviceId.toLowerCase())) { + reject([['deviceId is not MAC', BLHErrorCode.SYSTEM_ERROR]]) + return + } + this.queryBLECharacteristic(deviceId, serviceId).then(desc => { + console.debug( + '[QAFAPI] desc = ' + + JSON.stringify(desc) + ) + const descriptors = [] + const descriptor = { + serviceUuid: serviceId.toLowerCase(), + characteristicUuid: characteristicId.toLowerCase(), + descriptorUuid: desc.descriptorUuid, + descriptorValue: desc.descriptorValue, + } + descriptors.push(descriptor) + + const characteristicIn = { + serviceUuid: serviceId.toLowerCase(), + characteristicUuid: characteristicId.toLowerCase(), + characteristicValue: this.characteristicValue, + descriptors: descriptors, + } + console.debug( + '[QAFAPI] BLECharacteristic = ' + + JSON.stringify(characteristicIn) + ) + // 向服务端发送设置通知此特征值请求notify + let GattClient = null + let isNotify + if (this.gattClient && this.deviceIdBle === deviceId) { + try { + isNotify = this.gattClient.setNotifyCharacteristicChanged( + characteristicIn, + state + ) + } catch (err) { + reject([[err.message, ErrorCode.PARAMETER_ERROR]]) + console.error( + '[QAFAPI]setNotifyCharacteristicChanged errCode:' + + err.code + + ',errMessage:' + + err.message + ) + return + } + } else { + try { + GattClient = BluetoothBase.createGattClientDevice(deviceId) + isNotify = GattClient.setNotifyCharacteristicChanged( + characteristicIn, + state + ) + } catch (err) { + reject([[err.message, ErrorCode.PARAMETER_ERROR]]) + console.error( + '[QAFAPI]setNotifyCharacteristicChanged errCode:' + + err.code + + ',errMessage:' + + err.message + ) + return + } + } + // 缺少低功耗设备未连接状态的失败回调(暂不支持直接获取) + if (isNotify) { + console.debug('[QAFAPI] notify success') + resolve('ok') + } else { + reject([['property not support', BLHErrorCode.PROPERTY_NOT_SUPPORT]]) + } + }) + }) + } + + getBLEDeviceRSSI(deviceId) { + return new Promise((resolve, reject) => { + if (this.gattClient && this.deviceIdBle === deviceId) { + this.gattClient.getRssiValue().then((res) => { + resolve(res) + }).catch(err => { + reject(err.message) + }) + } else { + try { + const gattClient = BluetoothBase.createGattClientDevice(deviceId) + gattClient.connect() + this.gattClient = gattClient + this.deviceIdBle = deviceId + gattClient.getRssiValue().then(res => { + resolve(res) + }).catch(err => { + reject(err.message) + }) + } catch (err) { + reject(err.message) + } + } + }) + } + + // device输出模板 + getTemp() { + return { + 'RSSI': '', // 当前蓝牙设备的信号强度 + 'localName': '', // 当前蓝牙设备的广播数据段中的 LocalName 数据段 + 'advertisData': '', // 当前蓝牙设备的广播数据段中的 ManufacturerData 数据段 + 'advertisServiceUUIDs': '', // 当前蓝牙设备的广播数据段中的 ServiceUUIDs 数据段 + 'name': '', // 蓝牙设备名称,某些设备可能没有。 + 'serviceData': '', // 当前蓝牙设备的广播数据段中的 ServiceData数据段,返回结构为{"service uuid string": ArrayBuffer} + 'deviceId': '' // 用于区分设备的id + } + } + + // 判断对象是否重复 + // [{"deviceId":'',xxx}] + isRepeat(arr, deviceId) { + return arr.some(obj => { + return obj.deviceId === deviceId + }) + } + + // 弹框模板 + promptTemp(message) { + return PromptBase.ohosShowDialog({ // promise + message, + buttons: [ + { + text: DEFAULT.REFUSE_BUTTON, + color: '#1358e7' + }, + { + text: DEFAULT.ALLOW_BUTTON, + color: '#1358e7' + } + ] + }) + } +} diff --git a/ohos/AdvancedAPI_OHOS/src/base/module/Brightness/BrightnessBaseModule.js b/ohos/AdvancedAPI_OHOS/src/base/module/Brightness/BrightnessBaseModule.js new file mode 100644 index 0000000000..b2dea4d969 --- /dev/null +++ b/ohos/AdvancedAPI_OHOS/src/base/module/Brightness/BrightnessBaseModule.js @@ -0,0 +1,103 @@ +import { jsMethod } from '../../decorators' +import { context } from '../../bridge/abilityBase' +import { BrightnessBase } from '../../bridge/brightnessBase' +import { ErrorCode } from '../../util/ErrorCode' +import { isNumber } from '../../util/checkDataType' +import window from '@ohos.window' + +export class BrightnessBaseModule { + @jsMethod({ alias: 'getValue', common: false, callback: true }) + getValue() { + return new Promise((resolve, reject) => { + try { + window.getLastWindow(context).then(windowClass => { + const properties = windowClass.getWindowProperties() + let value = properties.brightness + if (!value || value < 0) { + value = Number(BrightnessBase.ohoGetValue()) / 255 + } + const brightness = { + value: Math.round(value * 255) + } + console.debug('[QAFAPI] getValue success, brightness = ' + JSON.stringify(brightness)) + resolve([brightness]) + }) + } catch (exception) { + reject([['Failed to get brightness']]) + console.error('Failed to obtain the window properties. Cause: ' + JSON.stringify(exception)) + } + }) + } + + @jsMethod({ alias: 'setValue', common: false, callback: true }) + setValue(object) { + return new Promise((resolve, reject) => { + const { value } = object + let params + if (value || value === 0) { + params = value + } else { + reject([['inalid param', ErrorCode.PARAMETER_ERROR]]) + return + } + if (!isNumber(params)) { + reject([['inalid param', ErrorCode.PARAMETER_ERROR]]) + return + } + let Num = Math.floor(params) + if (Num < 0) { + Num = 1 + } else if (Num > 255) { + Num = 255 + } + const brightness = Num / 255 + try { + window.getLastWindow(context).then((windowClass) => { + windowClass.setWindowBrightness(brightness, (err) => { + if (err.code) { + reject([['setWindowBrightness fail']]) + console.error('[QAFAPI] Failed to set the brightness. Cause: ' + JSON.stringify(err)) + return + } + resolve('successed to set') + console.info('[QAFAPI] Succeeded in setting the brightness.') + }) + }) + } catch (error) { + console.error('[QAFAPI] Failed to set setting of brightness. Cause:' + JSON.stringify(error)) + reject([['setWindowBrightness fail']]) + } + }) + } + + @jsMethod({ alias: 'setKeepScreenOn', common: false, callback: true }) + setKeepScreenOn(object) { + return new Promise((resolve, reject) => { + if (object && object.keepScreenOn !== '' && object.keepScreenOn !== null) { + const { keepScreenOn } = object + if (typeof (keepScreenOn) === 'boolean') { + try { + window.getLastWindow(context).then(windowClass => { + windowClass.setWindowKeepScreenOn(keepScreenOn, (err) => { + if (err.code) { + console.error('[QAFAPI] Failed to set the screen to be always on. Cause: ' + JSON.stringify(err)) + reject([['handling failed']]) + return + } + resolve(['handling success']) + console.info('[QAFAPI] Succeeded in setting the screen to be always on.') + }) + }) + } catch (exception) { + console.error('[QAFAPI] Failed to set the screen to be always on. exception: ' + JSON.stringify(exception)) + reject([['handling failed']]) + } + } else { + reject([['inalid param', ErrorCode.PARAMETER_ERROR]]) + } + } else { + reject([['inalid param', ErrorCode.PARAMETER_ERROR]]) + } + }) + } +} diff --git a/ohos/AdvancedAPI_OHOS/src/base/module/Network/NetworkBaseModule.js b/ohos/AdvancedAPI_OHOS/src/base/module/Network/NetworkBaseModule.js new file mode 100644 index 0000000000..92da6ddcef --- /dev/null +++ b/ohos/AdvancedAPI_OHOS/src/base/module/Network/NetworkBaseModule.js @@ -0,0 +1,72 @@ +import { RadioBase, netWorkConnState } from '../../bridge/radioBase' +import { WifiBase } from '../../bridge/wifiBase' +import { jsMethod } from '../../decorators/index' + +export default class NetworkBaseModule { + signalType (resultObj) { + switch (resultObj) { + case netWorkConnState.GSM: + case netWorkConnState.CDMA: + resultObj = { + metered: true, + type: '2G' + } + break + case netWorkConnState.WCDMA: + case netWorkConnState.TDSCDMA: + resultObj = { + metered: true, + type: '3G' + } + break + case netWorkConnState.LTE: + resultObj = { + metered: true, + type: '4G' + } + break + case netWorkConnState.NR: + resultObj = { + metered: true, + type: '5G' + } + break + case netWorkConnState.UNKNOWN: + resultObj = { + metered: true, + type: 'none' + } + break + } + return resultObj + } + + // 获取网络类型 + @jsMethod({ alias: 'getType', common: false, callback: true }) + async getType() { + const linkedInfo = await WifiBase.ohoGetLinkedInfo() + let resultObj = { + metered: false, + type: 'wifi' + } + // 板子不支持获取默认数据卡槽,打桩为0 + const defaultSlotId = 0 + return new Promise((resolve, reject) => { + if (linkedInfo.connState === 4) { + resolve([resultObj]) + return + } + RadioBase.ohoGetSignalInformation(defaultSlotId).then(data => { + if (data && data.signalType) { + resultObj = this.signalType(data.signalType) + resolve([resultObj]) + } else { + resultObj.type = 'none' + resolve([resultObj]) + } + }).catch(err => { + reject([[' Failed to get type:' + err.data, err.code]]) + }) + }) + } +} diff --git a/ohos/AdvancedAPI_OHOS/src/base/module/Wifi/WifiBaseModule.js b/ohos/AdvancedAPI_OHOS/src/base/module/Wifi/WifiBaseModule.js new file mode 100644 index 0000000000..8ec1f59c86 --- /dev/null +++ b/ohos/AdvancedAPI_OHOS/src/base/module/Wifi/WifiBaseModule.js @@ -0,0 +1,93 @@ +import { jsMethod } from '../../decorators' +import { WifiBase } from '../../bridge/wifiBase' +import { ErrorCode, WifiErrorCode } from '../../util/ErrorCode' + +export class WifiBaseModule { + constructor() { + this.SecureType = { + WPA: 'wpa', + WEP: 'wep', + } + } + isSecure(capabilities = '') { + let result = false + capabilities = capabilities.toLowerCase() + if ( + capabilities.includes(this.SecureType.WPA) || + capabilities.includes(this.SecureType.WEP) + ) { + result = true + } + return result + } + + getSignalStrength(value) { + return value + 100 + } + + @jsMethod({ alias: 'scan', common: false }) + scan() { + return new Promise((resolve, reject) => { + if (!WifiBase.isWifiActive()) { + reject([['wifi not turned on', WifiErrorCode.WIFI_NOT_TURNED_ON]]) + return + } + const isScan = WifiBase.scan() + if (isScan) { + resolve([['scan success']]) + } else { + reject([['scan fail', WifiErrorCode.WIFI_NOT_TURNED_ON]]) + } + }) + } + + @jsMethod({ alias: 'getConnectedWifi', common: false }) + getConnectedWifi(partialInfo) { + return new Promise((resolve, reject) => { + if (!WifiBase.isWifiActive()) { + reject([['wifi not turned on', WifiErrorCode.WIFI_NOT_TURNED_ON]]) + return + } + + WifiBase.ohoGetLinkedInfo().then(async (wifiInfo) => { + if (wifiInfo.connState === WifiBase.ConnState.DISCONNECTED) { + reject([['wifi is not connected', ErrorCode.COMMON_ERROR]]) + return + } + + if (partialInfo) { + const result = { + SSID: wifiInfo.ssid, + } + resolve([[result]]) + return + } + + const result = { + BSSID: wifiInfo.bssid, + SSID: wifiInfo.ssid, + frequency: wifiInfo.frequency, + signalStrength: this.getSignalStrength(wifiInfo.rssi), + secure: false, + } + + let capabilities + const scanLists = await WifiBase.getScanInfos() + const length = scanLists.length + for (let i = 0; i < length; i++) { + if ( + scanLists[i].bssid === result.BSSID && + scanLists[i].ssid === result.SSID + ) { + capabilities = scanLists[i].capabilities + break + } + } + if (capabilities) { + result.secure = this.isSecure(capabilities) + } + resolve([[result]]) + }) + }) + } +} diff --git a/ohos/AdvancedAPI_OHOS/src/base/util/ErrorCode.js b/ohos/AdvancedAPI_OHOS/src/base/util/ErrorCode.js new file mode 100644 index 0000000000..c6bdd0c866 --- /dev/null +++ b/ohos/AdvancedAPI_OHOS/src/base/util/ErrorCode.js @@ -0,0 +1,162 @@ +// 通用错误码 +export const ErrorCode = { + SHARE_INSTALLED_ERROR: -1001, // 第三方分享,分享的应用未安装 + SUCCESS: 0, // 成功 + COMMON_ERROR: 200, // 失败,其他通用错误 + USER_REJECT: 201, // 用户拒绝授权 + PARAMETER_ERROR: 202, // 参数为空或者参数错误 + SERVICE_UNAVIALABLE: 203, // 服务不可用 + SERVICE_TIMEOUT: 204, // 请求超时 + NOT_SUPPORT_SERVICE_COUNTRY: 205, // 不支持该服务地/设备 + NOT_IN_WHITE_LIST: 206, // 不在白名单 + SYSTEM_PERMISSION_DENIAL: 207, // 系统权限拒绝 + IO_ERROR: 300, // IO错误 + FILE_NOT_FOUND: 301, // 文件路径不存在 + FILE_EXIST: 302, // 文件已存在 + FILE_EXTENSION_NOT_EXIST: 303, // 文件后缀名不存在 + FILE_PATH_NOT_LEGAL: 304, // 文件路径不合法 + WEB_PAGE_NOT_FOUND: 404, // web组件404错误 + QUICKAPP_IN_BACKGROUND: 500, // 应用在后台无法进行操作 + LOCATION_SWITCH_CLOSED: 1000, // 系统位置开关关闭 + PAY_CHECKKEY_FAIL: 1001, // 支付公钥验签失败 + SIM_NOT_FOUND: 1001, // 未插入SIM卡 + SIGNIN_AUTH_FAIL: 1002, // 应用鉴权失败 + OPERATORS_GET_FAIL: 1002, // 获取运营商信息失败 + ALARM_SYSTEM_ERROR: 1003, // 系统不支持闹钟设置 + AGD_COMMON_ERROR: 2001, // AGD SDK接口返回错误 + WIDGET_NOT_SUPPORT: 2001, // 设备不支持在桌面添加快应用中心widget小组件 + CARD_CALL_QUICK_APP_CENTER_FAIL: 2003, // 快卡与快应用中心通信失败 + BI_REPORT_ERROR: 4001, // BI Report接口返回错误 + PAY_CANCEL_CODE: 30000, // 用户取消支付 + PAY_CERTIFICATION_CODE: 30102, // 实名认证失败 +} + +// 蓝牙错误码 +export const BLHErrorCode = { + OK: 0, // 正常 + OTHER_ERRORS: 200, // 其他错误 + NOT_INIT: 10000, // 未启动连接 + NOT_AVAILABLE: 10001, // 当前蓝牙适配器不可用 + NO_DEVICE: 10002, // 没有找到指定设备 + CONNECTION_FAIL: 10003, // 连接失败 + NO_SERVICE: 10004, // 没有找到指定服务 + NO_CHARACTERISTIC: 10005, // 没有找到指定特征值 + NO_CONNECTION: 10006, // 当前连接已断开 + PROPERTY_NOT_SUPPORT: 10007, // 当前特征值不支持此操作 + SYSTEM_ERROR: 10008, // 其余所有系统上报的异常 + SYSTEM_NOT_SUPPORT: 10009, // 系统版本低于 5.0 不支持 BLE + LOCATION_NOT_TURN_ON: 10010, // 系统位置开关关闭 + NO_SUCH_INTERFACE: 10100, // 获取连接状态失败 + DEVICE_DOES_NOT_EXIST: 10101, // 设备不存在 + NOT_AVAILABLE_TIRAMISU: 10102, // 在安卓13及以上版本不可用 +} + +// WIFI错误码 +export const WifiErrorCode = { + PASSWORD_ERROR: 1000, // Wi-Fi密码错误 + CONNECTION_TIMEOUT: 1001, // 连接超时 + DUPLICATE_REQUEST: 1002, // 重复连接 Wi-Fi + WIFI_NOT_TURNED_ON: 1003, // 未打开Wi-Fi开关 + GPS_NOT_TURNED_ON: 1004, // 未打开GPS定位开关 + INVALID_SSID: 1005, // 无效SSID +} + +// 广告错误码 +export const ADErrorCode = { + STANDARD_SERVER: 1000, // 后端错误 + STANDARD_PARAM: 1001, // 参数错误 + STANDARD_INVALID_UNIT: 1002, // 广告单元无效 + STANDARD_INNER_ERROR: 1003, // 内部错误 + STANDARD_NO_RESOURCE: 1004, // 无合适的广告 + STANDARD_TOO_OFTEN: 1100, // 过于频繁调用相关API + STANDARD_INVALID_METHOD: 1102, // 调用了不支持的方法 + STANDARD_NET: 1104, // 网络错误 + STANDARD_UNKNOWN: 2000, // 未知错误 +} + +// 视频错误码 +export const VideoErrorCode = { + CANCEL_TASK: 100, // 取消任务 + COMMON_ERROR: 200, // 接口功能异常 + PARAMETER_ERROR: 202, // 参数错误 + EMPTY_ENTRY: 203, // 找不到实例 + REPEATED_CAL: 205, // 压缩任务已创建,无需再调用第二次 + IO_ERROR: 300, // IO错误 + INVALID_VIDEO: 1001, // 原视频无效 +} + +// 文本转音频错误码 +export const TtaErrorCode = { + FAILED: 1000, // 合成失败 + SYSTEM_SDK_VERSION_DOES_NOT_SUPPORT: 1001, // 系统SDK版本不支持 + INITIALIZATION_FAILED: 1002, // 初始化失败 + TEXT_LENGTH_EXCEEDS_LIMIT: 1003, // 输入文本的长度超过限值 + LANGUAGE_NOT_SUPPORTED: 1004, // 语言不支持 + IO_EXCEPTION: 1005, // IO异常 +} + +// 活体检测错误码 +export const BiometriverifyErrorCode = { + NO_DYNAMIC_CAMERA_PERMISSION: 201, // 用户拒绝,获取相机权限失败 + FREQUENT_OPERATIONS: 205, // 操作频繁,上次操作还未完成 + NO_SYSTEM_CAMERA_PERMISSION: 207, // 系统权限拒绝,获取相机权限失败 + NOT_SUPPORT_SERVICE_COUNTRY: 220, // 当前服务国家/地区不支持此功能 + NO_PERMISSION: 1001, // 没有权限使用该接口 + VERIFY_LIVING_PERSON_CANCEL: 1002, // 活体检测取消 + OPEN_CAMERA_FAIL: 1003, // 活体检测打开相机失败 + VERIFY_INIT_FAIL: 1004, // 活体检测初始化失败 + VERIFY_LIVING_PERSON_FAIL: 1005, // 活体检测失败 + VERIFY_LIVING_PERSON_TIMEOUT: 1006, // 活体检测超时 +} + +// 应用上下文错误码 +export const UserUpdateErrorCode = { + APPLY_RESULT_SUCCESS: 200, // 执行更新成功。 + APPLY_RESULT_NOT_READY: 201, // 当前更新版本未就绪 + APPLY_RESULT_REPEAT_REQUEST: 202, // 重复调用 + UPDATE_ERROR_CODE_CONFLICT: 1001, // 更新的版本与当前版本证书冲突。 + UPDATE_ERROR_SIZE_EXCEEDED: 1002, // rpk大小超出限制 + UPDATE_ERROR_SIZE_NETWORK: 1003, // 网络问题,下载更新失败 + UPDATE_ERROR_IO: 1004, // 网络问题,下载更新失败 +} + +// websocket错误码 +export const WebscoketErrorCode = { + NORMAL_CLOSURE: 1000, // Normal Closure + GOING_AWAY: 1001, // Going Away + PROTOCOL_ERROR: 1002, // Protocol Error + UNSUPPORTED_DATA: 1003, // Unsupported Data + NO_STATUS_RECVD: 1005, // No Status Recvd + ABNORMAL_CLOSURE: 1006, // Abnormal Closure + INVALID_FRAME_PAYLOAD_DATA: 1007, // Invalid frame payload data + POLICY_VIOLATION: 1008, // Policy Violation + MESSAGE_TOO_BIG: 1009, // Message too big + MISSING_EXTENSION: 1010, // Missing Extension + INTERNAL_ERROR: 1011, // Internal Error + SERVICE_RESTART: 1012, // Service Restart + TRY_AGAIN_LATER: 1013, // Try Again Later + BAD_GATEWAY: 1014, // Bad Gateway + BAD_GATEWAY2: 1015, // Bad Gateway +} + +// 应用管理错误码 +export const AppManagerErrorCode = { + CANNOT_FOUND_APP: 1000 +} + +// tts错误码 +export const TtsErrorCode = { + ERROR: 200, // 通用错误。 + INVALIDPARAM: 202, // 参数错误。 + ERROR_NETWORK: 1001, // 网络连接错误。 + ERROR_NETWORK_TIMEOUT: 1002, // 网络连接超时。 + ERROR_NOT_INSTALLED_YET: 1003, // 下载语音数据未完成。 + ERROR_OUTPUT: 1004, // 输出到音频设备失败。 + ERROR_SERVICE: 1005, // TTS服务失败。 + ERROR_SYNTHESIS: 1006, // TTS引擎合成语音失败。 +} + +export const AccountErrorCode = { + SESSION_INVALID: 102 // session无效。 +} + diff --git a/ohos/AdvancedAPI_OHOS/src/base/util/Result.js b/ohos/AdvancedAPI_OHOS/src/base/util/Result.js new file mode 100644 index 0000000000..157c2ac108 --- /dev/null +++ b/ohos/AdvancedAPI_OHOS/src/base/util/Result.js @@ -0,0 +1,27 @@ +/** + * Copyright (c) Huawei Technologies Co., Ltd. 2022-2022. All rights reserved. + * Description: 模块返回参数封装 + * Author: weisufang + * Create: 03/22/2022 + * Notes: N/A + */ + +import { dataToArray } from './typeTransForm' + +export default class Result { + static success (data, ignoreComplete = false, ifKeepAlive = false) { + return { method: 'success', arguments: dataToArray(data), ignoreComplete, ifKeepAlive } + } + static fail (data, ignoreComplete = false, ifKeepAlive = false) { + return { method: 'fail', arguments: dataToArray(data), ignoreComplete, ifKeepAlive } + } + static cancel (data, ignoreComplete = false, ifKeepAlive = false) { + return { method: 'cancel', arguments: dataToArray(data), ignoreComplete, ifKeepAlive } + } + static callback (data, ignoreComplete = false, ifKeepAlive = false) { + return { method: 'callback', arguments: dataToArray(data), ignoreComplete, ifKeepAlive } + } + static destroy (data, ignoreComplete = false, ifKeepAlive = false) { + return { method: 'destroy', arguments: dataToArray(data), ignoreComplete, ifKeepAlive } + } +} diff --git a/ohos/AdvancedAPI_OHOS/src/base/util/checkDataType.js b/ohos/AdvancedAPI_OHOS/src/base/util/checkDataType.js new file mode 100644 index 0000000000..d41c76a300 --- /dev/null +++ b/ohos/AdvancedAPI_OHOS/src/base/util/checkDataType.js @@ -0,0 +1,230 @@ +/** + * Copyright (c) Huawei Technologies Co., Ltd. 2022-2022. All rights reserved. + * Description: 检查数据类型工具函数 + * Author: xuxiaofei + * Create: 03/17/2022 + * Notes: N/A + */ + +// 判断MIC地址格式是否正确(deviceid) +function isMac (str) { + return /^[A-Fa-f\d]{2}:[A-Fa-f\d]{2}:[A-Fa-f\d]{2}:[A-Fa-f\d]{2}:[A-Fa-f\d]{2}:[A-Fa-f\d]{2}$/.test(str) +} + +// 判断UUID是否格式正确 +function isUuid (str) { + return /^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$/.test(str) +} + +// 判断字符串是否为全小写 +function isLower (str) { + return str === str.toLowerCase() +} + +// 判断字符串是否包含中文 +function isIncludeChinese (str) { + const regChinese = new RegExp('[\u4e00-\u9fa5]+', 'g') + return regChinese.test(str) +} + +// 数据类型是否为int +function isInt (data) { + if (isNumber(data)) { + return (/(^[1-9]\d*$)/.test(data)) + } +} + +// 数据类型是否为number +function isNumber (data) { + return typeof data === 'number' && !Number.isNaN(data) && Number.isFinite(data) +} + +// 数据类型是否为string +function isString (data) { + return typeof data === 'string' +} + +// 数据类型是否为boolean +function isBoolean (data) { + return typeof data === 'boolean' +} + +// 数据类型是否为function +function isFunction (data) { + return typeof data === 'function' +} + +// 数据类型是否为arraybuffer +function isArrayBuffer (data) { + return Object.prototype.toString.call(data) === '[object ArrayBuffer]' +} + +// 数据类型是否为Uint8Array +function isUint8Array (data) { + return Object.prototype.toString.call(data) === '[object Uint8Array]' +} + +// 判断url是否有效 +function isValidURL (url) { + const urlReg = /^https?:\/\/(([a-zA-Z0-9_-])+(\.)?)*(:\d+)?(\/.*)?(\?.*)?(#.*)?$/ + if (!isString(url)) { + return false + } + return urlReg.test(url) +} + +// 判断websocket的url是否有效 +function isValidURLofWS (url) { + const urlReg = /^wss?:\/\/(([a-zA-Z0-9_-])+(\.)?)*(:\d+)?(\/.*)?(\?.*)?(#.*)?$/ + if (!isString(url)) { + return false + } + return urlReg.test(url) +} + +// 判断uri是否有效 +function isValidURI (uri) { + const uriReg = /^(internal:\/\/|\/)?([^\s"':|*?<>\\]+\/)*([^\s"':|*?<>\\]+)?$/ + if (!isString(uri)) { + return false + } + // uri不允许出现.. + if (uri.indexOf('..') > -1) { + return false + } + return uriReg.test(uri) +} + +// 数据类型是否为null +function isNull (data) { + return data === null +} + +// 数据类型是否为undefined +function isUndefined (data) { + return (typeof data) === 'undefined' +} + +// 数据类型是否为数组 +function isArray (data) { + return Array.isArray(data) +} + +// 数据类型是否为16进制颜色码 +function isHexcolor (data) { + const regExp6 = /^#[0-9a-fA-F]{6}$/i + const regExp3 = /^#[0-9a-fA-F]{3}$/i + return regExp6.test(data) || regExp3.test(data) +} + +/** + * 通用校验接口checkDataType + * @param {*} data 待校验数据 + * @param {Boolean} isRequired 是否为必填项 + * @param {String | String[]} dataType 字符串或数组,预期的数据类型, + * 字符串支持:"string","number","boolean","function","arraybuffer","array","hexcolor"。 + * 支持上述字符串类型组成的数组,数组情况下满足其中一种类型即校验通过 + * @param {Function} customCheck 定制化校验方法,入参为data,需返回布尔 + * @returns {Boolean} 返回是否校验通过 + */ +function checkDataType (data, isRequired, dataType, customCheck) { + let result = false + try { + if (isRequired && (isNull(data) || isUndefined(data))) { + throw new Error('The param data is required') + } + if (!isString(dataType) && !isArray(dataType)) { + throw new Error('The param dataType should be a String or an Array') + } + if (!isNull(customCheck) && !isUndefined(customCheck) && !isFunction(customCheck)) { + throw new Error('If customCheck exist,it should be a Function') + } + + // 非必填时,如果没有该参数,直接返回true + if (!isRequired && (isNull(data) || isUndefined(data))) { + return true + } + if (isString(dataType)) { + result = checkSingleDataType(data, dataType) + } else if (isArray(dataType)) { + result = dataType.some(value => { + return checkSingleDataType(data, value) + }) + } + if (result && isFunction(customCheck)) { + result = customCheck(data) + } + } catch (error) { + console.log(error) + return false + } + return result +} +function checkSingleDataType (data, dataType) { + let result = false + switch (dataType) { + case 'string': + result = isString(data) + break + case 'number': + result = isNumber(data) + break + case 'boolean': + result = isBoolean(data) + break + case 'function': + result = isFunction(data) + break + case 'arraybuffer': + result = isArrayBuffer(data) + break + case 'array': + result = isArray(data) + break + case 'hexcolor': + result = isHexcolor(data) + break + case 'null': + result = isNull(data) + break + case 'undefined': + result = isUndefined(data) + break + default: + throw new Error('The param dataType is unsupport') + } + return result +} +function isJsonString (str) { + try { + if (typeof JSON.parse(str) === 'object') { + return true + } + } catch (e) { } + return false +} +// 判断号码是否有效 +function isValidDestNumber (data) { + const regExp = /^\+?([0-9]\d*|\s)+$/ + return regExp.test(data) +} +export { + isNumber, + isString, + isBoolean, + isFunction, + isArrayBuffer, + isUint8Array, + isValidURL, + isValidURLofWS, + isValidURI, + checkDataType, + isInt, + isArray, + isLower, + isJsonString, + isMac, + isUuid, + isValidDestNumber, + isIncludeChinese +} diff --git a/ohos/AdvancedAPI_OHOS/src/base/util/colors.js b/ohos/AdvancedAPI_OHOS/src/base/util/colors.js new file mode 100644 index 0000000000..c84eed8ee6 --- /dev/null +++ b/ohos/AdvancedAPI_OHOS/src/base/util/colors.js @@ -0,0 +1,150 @@ +export const colors = { + aliceblue: [240, 248, 255], + antiquewhite: [250, 235, 215], + aqua: [0, 255, 255], + aquamarine: [127, 255, 212], + azure: [240, 255, 255], + beige: [245, 245, 220], + bisque: [255, 228, 196], + black: [0, 0, 0], + blanchedalmond: [255, 235, 205], + blue: [0, 0, 255], + blueviolet: [138, 43, 226], + brown: [165, 42, 42], + burlywood: [222, 184, 135], + cadetblue: [95, 158, 160], + chartreuse: [127, 255, 0], + chocolate: [210, 105, 30], + coral: [255, 127, 80], + cornflowerblue: [100, 149, 237], + cornsilk: [255, 248, 220], + crimson: [220, 20, 60], + cyan: [0, 255, 255], + darkblue: [0, 0, 139], + darkcyan: [0, 139, 139], + darkgoldenrod: [184, 134, 11], + darkgray: [169, 169, 169], + darkgreen: [0, 100, 0], + darkgrey: [169, 169, 169], + darkkhaki: [189, 183, 107], + darkmagenta: [139, 0, 139], + darkolivegreen: [85, 107, 47], + darkorange: [255, 140, 0], + darkorchid: [153, 50, 204], + darkred: [139, 0, 0], + darksalmon: [233, 150, 122], + darkseagreen: [143, 188, 143], + darkslateblue: [72, 61, 139], + darkslategray: [47, 79, 79], + darkslategrey: [47, 79, 79], + darkturquoise: [0, 206, 209], + darkviolet: [148, 0, 211], + deeppink: [255, 20, 147], + deepskyblue: [0, 191, 255], + dimgray: [105, 105, 105], + dimgrey: [105, 105, 105], + dodgerblue: [30, 144, 255], + firebrick: [178, 34, 34], + floralwhite: [255, 250, 240], + forestgreen: [34, 139, 34], + fuchsia: [255, 0, 255], + gainsboro: [220, 220, 220], + ghostwhite: [248, 248, 255], + gold: [255, 215, 0], + goldenrod: [218, 165, 32], + gray: [128, 128, 128], + green: [0, 128, 0], + greenyellow: [173, 255, 47], + grey: [128, 128, 128], + honeydew: [240, 255, 240], + hotpink: [255, 105, 180], + indianred: [205, 92, 92], + indigo: [75, 0, 130], + ivory: [255, 255, 240], + khaki: [240, 230, 140], + lavender: [230, 230, 250], + lavenderblush: [255, 240, 245], + lawngreen: [124, 252, 0], + lemonchiffon: [255, 250, 205], + lightblue: [173, 216, 230], + lightcoral: [240, 128, 128], + lightcyan: [224, 255, 255], + lightgoldenrodyellow: [250, 250, 210], + lightgray: [211, 211, 211], + lightgreen: [144, 238, 144], + lightgrey: [211, 211, 211], + lightpink: [255, 182, 193], + lightsalmon: [255, 160, 122], + lightseagreen: [32, 178, 170], + lightskyblue: [135, 206, 250], + lightslategray: [119, 136, 153], + lightslategrey: [119, 136, 153], + lightsteelblue: [176, 196, 222], + lightyellow: [255, 255, 224], + lime: [0, 255, 0], + limegreen: [50, 205, 50], + linen: [250, 240, 230], + magenta: [255, 0, 255], + maroon: [128, 0, 0], + mediumaquamarine: [102, 205, 170], + mediumblue: [0, 0, 205], + mediumorchid: [186, 85, 211], + mediumpurple: [147, 112, 219], + mediumseagreen: [60, 179, 113], + mediumslateblue: [123, 104, 238], + mediumspringgreen: [0, 250, 154], + mediumturquoise: [72, 209, 204], + mediumvioletred: [199, 21, 133], + midnightblue: [25, 25, 112], + mintcream: [245, 255, 250], + mistyrose: [255, 228, 225], + moccasin: [255, 228, 181], + navajowhite: [255, 222, 173], + navy: [0, 0, 128], + oldlace: [253, 245, 230], + olive: [128, 128, 0], + olivedrab: [107, 142, 35], + orange: [255, 165, 0], + orangered: [255, 69, 0], + orchid: [218, 112, 214], + palegoldenrod: [238, 232, 170], + palegreen: [152, 251, 152], + paleturquoise: [175, 238, 238], + palevioletred: [219, 112, 147], + papayawhip: [255, 239, 213], + peachpuff: [255, 218, 185], + peru: [205, 133, 63], + pink: [255, 192, 203], + plum: [221, 160, 221], + powderblue: [176, 224, 230], + purple: [128, 0, 128], + rebeccapurple: [102, 51, 153], + red: [255, 0, 0], + rosybrown: [188, 143, 143], + royalblue: [65, 105, 225], + saddlebrown: [139, 69, 19], + salmon: [250, 128, 114], + sandybrown: [244, 164, 96], + seagreen: [46, 139, 87], + seashell: [255, 245, 238], + sienna: [160, 82, 45], + silver: [192, 192, 192], + skyblue: [135, 206, 235], + slateblue: [106, 90, 205], + slategray: [112, 128, 144], + slategrey: [112, 128, 144], + snow: [255, 250, 250], + springgreen: [0, 255, 127], + steelblue: [70, 130, 180], + tan: [210, 180, 140], + teal: [0, 128, 128], + thistle: [216, 191, 216], + tomato: [255, 99, 71], + turquoise: [64, 224, 208], + violet: [238, 130, 238], + wheat: [245, 222, 179], + white: [255, 255, 255], + whitesmoke: [245, 245, 245], + yellow: [255, 255, 0], + yellowgreen: [154, 205, 50] +} diff --git a/ohos/AdvancedAPI_OHOS/src/base/util/typeTransForm.js b/ohos/AdvancedAPI_OHOS/src/base/util/typeTransForm.js new file mode 100644 index 0000000000..7872fdcb19 --- /dev/null +++ b/ohos/AdvancedAPI_OHOS/src/base/util/typeTransForm.js @@ -0,0 +1,59 @@ +/** + * Copyright (c) Huawei Technologies Co., Ltd. 2022-2022. All rights reserved. + * Description: 数据类型转换工具函数 + * Author: pengweihang + * Create: 03/21/2022 + * Notes: N/A + */ + +function stringToArrayBuffer(str) { + const buffers = [] + let c + const len = str.length + for (let i = 0; i < len; i++) { + c = str.charCodeAt(i) + if (c >= 0x010000 && c <= 0x10FFFF) { + buffers.push(((c >> 18) & 0x07) | 0xF0) + buffers.push(((c >> 12) & 0x3F) | 0x80) + buffers.push(((c >> 6) & 0x3F) | 0x80) + buffers.push((c & 0x3F) | 0x80) + } else if (c >= 0x000800 && c <= 0x00FFFF) { + buffers.push(((c >> 12) & 0x0F) | 0xE0) + buffers.push(((c >> 6) & 0x3F) | 0x80) + buffers.push((c & 0x3F) | 0x80) + } else if (c >= 0x000080 && c <= 0x0007FF) { + buffers.push(((c >> 6) & 0x1F) | 0xC0) + buffers.push((c & 0x3F) | 0x80) + } else { + buffers.push(c & 0xFF) + } + } + const array = new Int8Array(buffers.length) + for (let i = 0; i <= buffers.length; i++) { + array[i] = buffers[i] + } + return array.buffer +} + +function dataToArray (obj) { + if (Array.isArray(obj)) { + return obj + } + return [obj] +} + +// 获取url上的参数 +function getUriParams (uri) { + const search = uri.split('?')[1] + const result = {} + if (search) { + const params = search.split('&') + params.forEach(item => { + const [key, value] = item.split('=') + result[key] = value + }) + } + return result +} + +export { stringToArrayBuffer, dataToArray, getUriParams } diff --git a/ohos/README.md b/ohos/README.md new file mode 100644 index 0000000000..76bf762da6 --- /dev/null +++ b/ohos/README.md @@ -0,0 +1,18 @@ +# 规格说明 + +高阶API扩展包:AdvancedAPI_OHOS + +鸿蒙化指导文档:docs + +样例工程:example +* DevEco Studio工程:ohos-example +* weex鸿蒙化工程:weex-example + +测试用例:Test +* weex测试用例工程:commonTest + +web高阶API扩展包:web_api_ohos + +鸿蒙化集成模块:web_scenekit_hsp + +鸿蒙化拓展插件包:weex-openharmony \ No newline at end of file diff --git a/ohos/docs/assets/175bef82-f6f8-4bb8-a49c-d6434ffab488.png b/ohos/docs/assets/175bef82-f6f8-4bb8-a49c-d6434ffab488.png new file mode 100644 index 0000000000..a650a9f13e Binary files /dev/null and b/ohos/docs/assets/175bef82-f6f8-4bb8-a49c-d6434ffab488.png differ diff --git a/ohos/docs/assets/17f22f52-d829-41e7-b3fa-eb4c5559b7a7.png b/ohos/docs/assets/17f22f52-d829-41e7-b3fa-eb4c5559b7a7.png new file mode 100644 index 0000000000..c5a720b721 Binary files /dev/null and b/ohos/docs/assets/17f22f52-d829-41e7-b3fa-eb4c5559b7a7.png differ diff --git a/ohos/docs/assets/23b82328-8505-406a-8a57-5c08e806eedd.png b/ohos/docs/assets/23b82328-8505-406a-8a57-5c08e806eedd.png new file mode 100644 index 0000000000..5e8344e3fa Binary files /dev/null and b/ohos/docs/assets/23b82328-8505-406a-8a57-5c08e806eedd.png differ diff --git a/ohos/docs/assets/25d694fe-9a25-4a89-89a4-64b5d38bed58.png b/ohos/docs/assets/25d694fe-9a25-4a89-89a4-64b5d38bed58.png new file mode 100644 index 0000000000..e4a73cd72f Binary files /dev/null and b/ohos/docs/assets/25d694fe-9a25-4a89-89a4-64b5d38bed58.png differ diff --git a/ohos/docs/assets/280fc365-e4b5-4a60-b923-04e41a99d86a.png b/ohos/docs/assets/280fc365-e4b5-4a60-b923-04e41a99d86a.png new file mode 100644 index 0000000000..85efa53e0e Binary files /dev/null and b/ohos/docs/assets/280fc365-e4b5-4a60-b923-04e41a99d86a.png differ diff --git a/ohos/docs/assets/2ef98fc1-56bc-4596-8a09-8bc20a99c87e.png b/ohos/docs/assets/2ef98fc1-56bc-4596-8a09-8bc20a99c87e.png new file mode 100644 index 0000000000..64cfc9429f Binary files /dev/null and b/ohos/docs/assets/2ef98fc1-56bc-4596-8a09-8bc20a99c87e.png differ diff --git a/ohos/docs/assets/31c7404f-b379-4f9e-ae50-be9fd87cc3d3.png b/ohos/docs/assets/31c7404f-b379-4f9e-ae50-be9fd87cc3d3.png new file mode 100644 index 0000000000..35255583c3 Binary files /dev/null and b/ohos/docs/assets/31c7404f-b379-4f9e-ae50-be9fd87cc3d3.png differ diff --git a/ohos/docs/assets/3bb62087-559d-4b6a-866f-6c18cc5c2bad.png b/ohos/docs/assets/3bb62087-559d-4b6a-866f-6c18cc5c2bad.png new file mode 100644 index 0000000000..98d31d59f8 Binary files /dev/null and b/ohos/docs/assets/3bb62087-559d-4b6a-866f-6c18cc5c2bad.png differ diff --git a/ohos/docs/assets/45a6a96e-2d2e-4ab3-baba-23285224d6dd.png b/ohos/docs/assets/45a6a96e-2d2e-4ab3-baba-23285224d6dd.png new file mode 100644 index 0000000000..ada86e9cf2 Binary files /dev/null and b/ohos/docs/assets/45a6a96e-2d2e-4ab3-baba-23285224d6dd.png differ diff --git a/ohos/docs/assets/54fbe58e-12c3-4b1d-8153-2a08e3357f0c.png b/ohos/docs/assets/54fbe58e-12c3-4b1d-8153-2a08e3357f0c.png new file mode 100644 index 0000000000..98f827f695 Binary files /dev/null and b/ohos/docs/assets/54fbe58e-12c3-4b1d-8153-2a08e3357f0c.png differ diff --git a/ohos/docs/assets/5539cf38-2042-4679-9bca-53d4dff8b95d.png b/ohos/docs/assets/5539cf38-2042-4679-9bca-53d4dff8b95d.png new file mode 100644 index 0000000000..73ad7cc35a Binary files /dev/null and b/ohos/docs/assets/5539cf38-2042-4679-9bca-53d4dff8b95d.png differ diff --git a/ohos/docs/assets/576798f5-e7e6-42f4-a936-9582505f0acd.png b/ohos/docs/assets/576798f5-e7e6-42f4-a936-9582505f0acd.png new file mode 100644 index 0000000000..cefcb798a5 Binary files /dev/null and b/ohos/docs/assets/576798f5-e7e6-42f4-a936-9582505f0acd.png differ diff --git a/ohos/docs/assets/5a66de35-18a7-4b8b-bd93-c58ef3daee78.png b/ohos/docs/assets/5a66de35-18a7-4b8b-bd93-c58ef3daee78.png new file mode 100644 index 0000000000..67b266066b Binary files /dev/null and b/ohos/docs/assets/5a66de35-18a7-4b8b-bd93-c58ef3daee78.png differ diff --git a/ohos/docs/assets/6d562a4d-1c1e-4e2f-9953-14c02a924ffd.png b/ohos/docs/assets/6d562a4d-1c1e-4e2f-9953-14c02a924ffd.png new file mode 100644 index 0000000000..fd13d7d679 Binary files /dev/null and b/ohos/docs/assets/6d562a4d-1c1e-4e2f-9953-14c02a924ffd.png differ diff --git a/ohos/docs/assets/6eb53446-30fd-4b5b-8656-765355fd32bc.png b/ohos/docs/assets/6eb53446-30fd-4b5b-8656-765355fd32bc.png new file mode 100644 index 0000000000..b5394c6913 Binary files /dev/null and b/ohos/docs/assets/6eb53446-30fd-4b5b-8656-765355fd32bc.png differ diff --git a/ohos/docs/assets/7516fe01-caa0-439c-a715-6b4a318a92b6.png b/ohos/docs/assets/7516fe01-caa0-439c-a715-6b4a318a92b6.png new file mode 100644 index 0000000000..3bea877a96 Binary files /dev/null and b/ohos/docs/assets/7516fe01-caa0-439c-a715-6b4a318a92b6.png differ diff --git a/ohos/docs/assets/7c34a3f4-f143-4b66-9081-9ca592675700.png b/ohos/docs/assets/7c34a3f4-f143-4b66-9081-9ca592675700.png new file mode 100644 index 0000000000..1e8ccb6131 Binary files /dev/null and b/ohos/docs/assets/7c34a3f4-f143-4b66-9081-9ca592675700.png differ diff --git a/ohos/docs/assets/7c445fe3-0c07-4266-a68d-080d1d013801.png b/ohos/docs/assets/7c445fe3-0c07-4266-a68d-080d1d013801.png new file mode 100644 index 0000000000..2abbd2287f Binary files /dev/null and b/ohos/docs/assets/7c445fe3-0c07-4266-a68d-080d1d013801.png differ diff --git a/ohos/docs/assets/819c8be1-23e8-4332-85f8-c937ae2867d9.png b/ohos/docs/assets/819c8be1-23e8-4332-85f8-c937ae2867d9.png new file mode 100644 index 0000000000..9e8a20d5d6 Binary files /dev/null and b/ohos/docs/assets/819c8be1-23e8-4332-85f8-c937ae2867d9.png differ diff --git a/ohos/docs/assets/89c55b9c-e257-46bf-99cf-324fbc36c719.png b/ohos/docs/assets/89c55b9c-e257-46bf-99cf-324fbc36c719.png new file mode 100644 index 0000000000..6728b14cf5 Binary files /dev/null and b/ohos/docs/assets/89c55b9c-e257-46bf-99cf-324fbc36c719.png differ diff --git a/ohos/docs/assets/92477799-9258-416f-9c15-9cd528f919a7.gif b/ohos/docs/assets/92477799-9258-416f-9c15-9cd528f919a7.gif new file mode 100644 index 0000000000..faf0319afd Binary files /dev/null and b/ohos/docs/assets/92477799-9258-416f-9c15-9cd528f919a7.gif differ diff --git a/ohos/docs/assets/Snipaste_2024-10-25_10-45-45.png b/ohos/docs/assets/Snipaste_2024-10-25_10-45-45.png new file mode 100644 index 0000000000..8d53e9bbbc Binary files /dev/null and b/ohos/docs/assets/Snipaste_2024-10-25_10-45-45.png differ diff --git a/ohos/docs/assets/Snipaste_2024-10-25_11-04-47.png b/ohos/docs/assets/Snipaste_2024-10-25_11-04-47.png new file mode 100644 index 0000000000..2bf2b1e3a1 Binary files /dev/null and b/ohos/docs/assets/Snipaste_2024-10-25_11-04-47.png differ diff --git a/ohos/docs/assets/Snipaste_2024-10-25_15-24-49.png b/ohos/docs/assets/Snipaste_2024-10-25_15-24-49.png new file mode 100644 index 0000000000..133a07bda5 Binary files /dev/null and b/ohos/docs/assets/Snipaste_2024-10-25_15-24-49.png differ diff --git a/ohos/docs/assets/Snipaste_2024-10-25_15-28-42.png b/ohos/docs/assets/Snipaste_2024-10-25_15-28-42.png new file mode 100644 index 0000000000..3bf06b4fb6 Binary files /dev/null and b/ohos/docs/assets/Snipaste_2024-10-25_15-28-42.png differ diff --git a/ohos/docs/assets/a328663c-49af-400c-a6b4-4bb58687f8c1.png b/ohos/docs/assets/a328663c-49af-400c-a6b4-4bb58687f8c1.png new file mode 100644 index 0000000000..653e811ff0 Binary files /dev/null and b/ohos/docs/assets/a328663c-49af-400c-a6b4-4bb58687f8c1.png differ diff --git a/ohos/docs/assets/a62d1304-0d15-427f-af2f-179dcf7373a6.png b/ohos/docs/assets/a62d1304-0d15-427f-af2f-179dcf7373a6.png new file mode 100644 index 0000000000..016c0c5c68 Binary files /dev/null and b/ohos/docs/assets/a62d1304-0d15-427f-af2f-179dcf7373a6.png differ diff --git a/ohos/docs/assets/b6302f87-2db1-470b-ac09-0f2da0e9374a.png b/ohos/docs/assets/b6302f87-2db1-470b-ac09-0f2da0e9374a.png new file mode 100644 index 0000000000..de5b08f0cb Binary files /dev/null and b/ohos/docs/assets/b6302f87-2db1-470b-ac09-0f2da0e9374a.png differ diff --git a/ohos/docs/assets/c61700cc-0d3f-4f4c-8491-6bdced2e5e3c.png b/ohos/docs/assets/c61700cc-0d3f-4f4c-8491-6bdced2e5e3c.png new file mode 100644 index 0000000000..ee2f8339d8 Binary files /dev/null and b/ohos/docs/assets/c61700cc-0d3f-4f4c-8491-6bdced2e5e3c.png differ diff --git a/ohos/docs/assets/cb897828-c91b-4c90-ba93-edd725633983.png b/ohos/docs/assets/cb897828-c91b-4c90-ba93-edd725633983.png new file mode 100644 index 0000000000..dc14f5ea78 Binary files /dev/null and b/ohos/docs/assets/cb897828-c91b-4c90-ba93-edd725633983.png differ diff --git a/ohos/docs/assets/cc03849e-a55f-4952-afa4-6e757b35eab6.png b/ohos/docs/assets/cc03849e-a55f-4952-afa4-6e757b35eab6.png new file mode 100644 index 0000000000..9241898f6d Binary files /dev/null and b/ohos/docs/assets/cc03849e-a55f-4952-afa4-6e757b35eab6.png differ diff --git a/ohos/docs/assets/cd052d56-d6c0-4594-9937-de434d39d53a.png b/ohos/docs/assets/cd052d56-d6c0-4594-9937-de434d39d53a.png new file mode 100644 index 0000000000..e378619f60 Binary files /dev/null and b/ohos/docs/assets/cd052d56-d6c0-4594-9937-de434d39d53a.png differ diff --git a/ohos/docs/assets/dede7776-303e-4c3f-a6a4-a366e6224120.png b/ohos/docs/assets/dede7776-303e-4c3f-a6a4-a366e6224120.png new file mode 100644 index 0000000000..2f453af97b Binary files /dev/null and b/ohos/docs/assets/dede7776-303e-4c3f-a6a4-a366e6224120.png differ diff --git a/ohos/docs/assets/e435707f-4662-4814-a885-314a70f7b33c.png b/ohos/docs/assets/e435707f-4662-4814-a885-314a70f7b33c.png new file mode 100644 index 0000000000..80529e50f1 Binary files /dev/null and b/ohos/docs/assets/e435707f-4662-4814-a885-314a70f7b33c.png differ diff --git a/ohos/docs/assets/e624406a-3c73-40af-85fb-0aa9f07e2909.png b/ohos/docs/assets/e624406a-3c73-40af-85fb-0aa9f07e2909.png new file mode 100644 index 0000000000..3c67f9b288 Binary files /dev/null and b/ohos/docs/assets/e624406a-3c73-40af-85fb-0aa9f07e2909.png differ diff --git a/ohos/docs/assets/edb18e95-e129-4e8c-b239-a9ea0a253075.png b/ohos/docs/assets/edb18e95-e129-4e8c-b239-a9ea0a253075.png new file mode 100644 index 0000000000..a2209a27de Binary files /dev/null and b/ohos/docs/assets/edb18e95-e129-4e8c-b239-a9ea0a253075.png differ diff --git a/ohos/docs/assets/f0453475-e095-4049-b2f0-eae3fd4c0f3c.png b/ohos/docs/assets/f0453475-e095-4049-b2f0-eae3fd4c0f3c.png new file mode 100644 index 0000000000..12d3c25887 Binary files /dev/null and b/ohos/docs/assets/f0453475-e095-4049-b2f0-eae3fd4c0f3c.png differ diff --git "a/ohos/docs/weex\351\270\277\350\222\231\345\214\226\346\214\207\345\257\274\346\226\207\346\241\243.md" "b/ohos/docs/weex\351\270\277\350\222\231\345\214\226\346\214\207\345\257\274\346\226\207\346\241\243.md" new file mode 100644 index 0000000000..9c87185d64 --- /dev/null +++ "b/ohos/docs/weex\351\270\277\350\222\231\345\214\226\346\214\207\345\257\274\346\226\207\346\241\243.md" @@ -0,0 +1,3623 @@ +# 一、框架介绍 + +当前 Weex 框架,没有鸿蒙 SDK 版本。Weex-Web 替代方案路线与 weex 鸿蒙平台 SDK 路线不同,使用了 **ArkWeb** + **原生ArkTS** 混合方式替代 Weex 1.0 框架,没有对 Weex 框架自身侵入式增加鸿蒙端平台的适配, 而是提供 babel/webpack 插件等脚本,在编译期对 weex 工程进行少许源码改动,注入鸿蒙相关适配代码,最后打包成bundle产物运行在 ArkWeb 容器来达到鸿蒙化 weex 项目的目的。 + +# 二、架构介绍 + +Weex-Web 方案的能力封装在 `webScenekitHsp` 中,包括页面管理、跨页面通信、全局监听事件、模版预热、双端通信、自定义拓展组件等。 + +- 页面管理: 核心服务,实现全局路由和web容器资源统一管理,支撑weex鸿蒙化页面调度场景; +- 跨页面通信: 提供 `BroadcastChannel` 机制允许页面之间进行通信; +- 全局监听事件: 提供 `GlobalEvent` 机制监听全局事件; +- 模板预热: 对高频页面提前进行预渲染; +- 双端通信: Web 环境与原生环境交互,提供注册 API 通道,允许 Web 环境通过通道访问原生侧; +- 自定义拓展组件: 使用Web组件的同层渲染能力,允许用户拓展自定义组件。 + +# 三、环境搭建 + +## 3.1 weex 工程编译打包 + +### 3.1.1 安装 nodejs 版本 + +注意:建议14版本,实际使用请根据工程环境而定 + +### 3.1.2 安装Weex CLI + +通过官网[设置开发环境 | WEEX (weexapp.com)](https://weexapp.com/zh/guide/develop/setup-develop-environment.html#%E5%AE%89%E8%A3%85%E4%BE%9D%E8%B5%96)安装脚手架工具并初始化项目。 +注意:使用weex -v 查看版本号为:Weex CLI version 2.0.0-beta.32 + +### 3.1.2 Weex项目鸿蒙化打包配置 + +#### 3.1.2.1 添加鸿蒙化打包命令及项目依赖 + +在package.json中添加鸿蒙编译打包命令 + +```shell +"build:harmony": "cross-env NODE_ENV=harmony apiEnv=prod ISHARMONY=true webpack --env.NODE_ENV=harmony", +``` + +由于新建weex项目中依赖版本过老,可直接替换以下版本依赖,其中`@ohos/weex-harmony`依赖包是由ohos/weex-openharmony工程中执行npm pack命令生成本地tgz包。 + +```json +"dependencies": { + "@antv/f2": "^3.3.9", + "@babel/polyfill": "^7.12.1", + "@babel/runtime": "^7.18.9", + "@ohos/weex-harmony": "D:/works/weex-master/ohos/weex-openharmony/ohos-weex-harmony-1.0.5.tgz", + "console": "^0.7.2", + "core-js": "^3.23.5", + "crypto-js": "^4.0.0", + "file-loader": "^5.0.2", + "gcanvas.js": "0.0.8", + "phantom-limb": "0.0.1", + "protobufjs": "^6.10.2", + "vue": "^2.6.11", + "weex-bindingx": "0.0.49", + "weex-vue-render": "^1.0.17", + "weixin-js-sdk": "^1.6.0", + "wolfy87-eventemitter": "^5.2.6" + }, + "devDependencies": { + "@appworks/doctor": "^0.4.1", + "@babel/core": "^7.18.9", + "@babel/plugin-transform-runtime": "^7.18.9", + "@babel/preset-env": "^7.18.9", + "@vue/compiler-dom": "^3.4.27", + "address": "^1.1.2", + "autoprefixer": "^8.0.0", + "babel-eslint": "^8.2.1", + "babel-helper-vue-jsx-merge-props": "^2.0.3", + "babel-loader": "^8.0.0", + "babel-plugin-component": "^1.1.1", + "babel-plugin-syntax-jsx": "^6.18.0", + "babel-plugin-transform-vue-jsx": "^3.5.0", + "clean-webpack-plugin": "^3.0.0", + "concurrently": "^8.2.2", + "cross-env": "^7.0.3", + "css-loader": "^1.0.0", + "eruda": "^2.11.2", + "eslint": "^5.12.0", + "eslint-config-standard": "^12.0.0", + "eslint-friendly-formatter": "^4.0.1", + "eslint-loader": "^2.1.1", + "eslint-plugin-import": "^2.14.0", + "eslint-plugin-node": "^8.0.1", + "eslint-plugin-promise": "^4.0.1", + "eslint-plugin-standard": "^4.0.0", + "eslint-plugin-vue": "^5.1.0", + "extract-text-webpack-plugin": "^3.0.2", + "filemanager-webpack-plugin": "^2.0.5", + "friendly-errors-webpack-plugin": "^1.6.1", + "fs-extra": "^5.0.0", + "glob": "^7.1.2", + "himalaya": "^1.1.0", + "html-webpack-plugin": "^3.2.0", + "html-webpack-plugin-for-multihtml": "^2.30.2", + "ip": "^1.1.5", + "less": "^3.8.0", + "less-loader": "^4.1.0", + "mini-css-extract-plugin": "^0.4.1", + "node-notifier": "^5.1.2", + "optimize-css-assets-webpack-plugin": "^5.0.0", + "patch-package": "^8.0.0", + "portfinder": "^1.0.13", + "postcss-import": "^11.0.0", + "postcss-loader": "^2.0.9", + "postcss-plugin-weex": "^0.1.6", + "qrcode-terminal": "^0.12.0", + "raw-loader": "^0.5.1", + "rimraf": "^2.6.2", + "script-ext-html-webpack-plugin": "^1.8.5", + "uglifyjs-webpack-plugin": "^1.2.7", + "url-loader": "^3.0.0", + "vconsole": "^3.15.1", + "vue-loader": "^15.2.6", + "vue-style-loader": "^4.1.1", + "vue-template-compiler": "^2.6.11", + "webpack": "^4.16.3", + "webpack-bundle-analyzer": "^4.8.0", + "webpack-cli": "^3.1.0", + "webpack-dev-middleware": "^3.1.3", + "webpack-dev-server": "^3.1.5", + "webpack-hot-middleware": "^2.22.3", + "webpack-merge": "^4.1.4", + "weex-vue-loader": "^0.7.0", + "weex-vue-precompiler": "^0.1.26" + } +``` + +#### 3.1.2.2 新增鸿蒙环境打包配置 + +在ohos/example目录下的weex-example样例工程中configs目录下获取`webpack.harmony.conf.js`文件并添加到本地weex项目中。 +在`webpack.harmony.conf.js`鸿蒙环境打包配置中打包所需的文件结构目录如下所示: + +```markup +└── weex-example # 所有项目的集合 + └── src # 项目名称,项目是一些html网页按照业务划分的集合,由伙伴定义 + ├── assets # 字体、样式资源目录 + ├── components # 组件目录 + ├── images # 图片资源目录 + ├── pages # 页面入口目录 + └── web # H5页面资源目录 +``` + +#### 3.1.2.3 修改替换公共打包配置并引入编译打包时执行loader插件 + +在ohos/example目录下的weex-example样例工程中configs目录下获取`webpack.dev.conf.js` 、`webpack.common.conf.js`、`qrcode-w-plugin.js`、`config.js`、`utils.js`、`transform-loader.js`文件并添加并替换到本地weex项目中。 + +#### 3.1.2.4 修改webpack打包配置文件 + +在项目根目录下的webpack.config.js打包配置文件中增加鸿蒙环境下引用的打包插件 + +```javascript +case 'harmony': + webpackConfig = require('./configs/webpack.harmony.conf'); + break; +``` + +#### 3.1.2.5 新增和修改babel配置文件并引入自定义babel插件 + +1. 在`.babelrc`文件中替换如下预设babel插件: + + ```json + { + "presets": [ + [ + "@babel/preset-env", + { + "modules": false, // 将esModule语法转化为其他模块语法 + "useBuiltIns": "usage", // 处理垫片引入方式,usage为按需引入 + "corejs": 3 + } + ] + ], + "plugins": [["@babel/plugin-transform-runtime"], [ + "component", + { + "libraryName": "@umetrip/ume-weex-ui", + "libDir": "packages", + "style": false + } + ]] + } + ``` +2. 在项目根目录下创建`babel.config.js`文件,并配置`weexTransform.js`转换插件 + + ```javascript + module.exports = { + plugins: ['./configs/weexTransform.js'] + } + ``` +3. 在ohos/example目录下的weex-example样例工程中configs目录下获取`weexTransform.js`文件并添加到本地weex项目中。 +#### 3.1.2.6 修改src/entry.js入口文件并初始化 +```javascript +import Vue from 'vue'; + +import weex from 'weex-vue-render'; + +const VConsole = require('vconsole'); + +if (!window.location.href.includes('static')) { + // eslint-disable-next-line no-new + new VConsole({ theme: 'dark' }); +} + +weex.init(Vue); +``` + + +### 3.1.3 安装依赖以及启动编译 + +```shell +npm install +npm run build:harmony +``` + +在工程目录下会生成编译产物frameworkTest_harmony_web.zip,解压后的frameworkTest_web文件夹为后续需要使用的web资源 + +![image](./assets/dede7776-303e-4c3f-a6a4-a366e6224120.png) + +## 3.2 webScenekitHsp 集成 + +1)将ohos目录下的web_scenekit_hsp文件夹复制到需要集成的工程目录下,如下所示 + +![image](./assets/Snipaste_2024-10-25_11-04-47.png) + +2)在工程根目录下的build-profile.json5中配置module字段,如下所示 + +```json +"modules": [ + { + "name": "entry", + "srcPath": "./entry", + "targets": [ + { + "name": "default", + "applyToProducts": [ + "default" + ] + } + ] + }, + { + "name": "WebScenekitHsp", + "srcPath": "./web_scenekit_hsp", + "targets": [ + { + "name": "default", + "applyToProducts": [ + "default" + ] + } + ] + } +] +``` + +3)在entry模块的oh-package.json5中dependencies引入webSencekitHsp模块 + +```json +"dependencies": { + "WebSceneKitHsp": "file:../web_scenekit_hsp" +} +``` + +4)webSencekitHsp模块的初始化 + +a、在entry模块下ets目录中创建GlobalThis.ets文件,然后在EntryAbility.ets(路径:src/main/ets/entryability/EntryAbility.ets)中的onCreate中保存context到GlobalThis中,供后续路由管理服务使用 + +```javascript +// GlobalThis .ets + +export class GlobalThis { + private constructor() { + } + + private static instance: GlobalThis; + private _uiContexts = new Map(); + + public static getInstance(): GlobalThis { + if (!GlobalThis.instance) { + GlobalThis.instance = new GlobalThis(); + } + return GlobalThis.instance; + } + + getContext(key: string): Context | undefined { + return this._uiContexts.get(key); + } + + setContext(key: string, value: Context): void { + this._uiContexts.set(key, value); + } +} +onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void { + GlobalThis.getInstance().setContext("GlobalContext", this.context) + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onCreate'); + } +``` + +b、在EntryAbility.ets中的onWindowStageCreate中对ExtWebController初始化,同时将UIContext保存到AppStorage中 + +```javascript +import { ExtWebController } from 'WebSceneKitHsp'; + +... +onWindowStageCreate(windowStage: window.WindowStage): void { + // Main window is created, set main page for this ability + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageCreate'); + + windowStage.loadContent('pages/Index', (err, data) => { + // 支持业务侧动态配置 将业务模块路径传入init 页面配置文件在每个业务模块根目录 + // 第一个参数为业务模块目录名,和rawfile下保持一致,最后一个参数是初始化web容器数量 + ExtWebController.init(['frameworkTest_web'], windowStage.getMainWindowSync().getUIContext(), this.context, 10); + AppStorage.setOrCreate("uiContext", windowStage.getMainWindowSync().getUIContext()); + }); + } +``` + +5)将weex工程中编译生成的frameworkTest_web放到鸿蒙工程的entry/src/main/resources/rawfile下 + +6)ExtWeb组件加载web页面 + +对外提供的扩展web组件。可在IDE工程page页面的容器控件中加载ExtWeb组件,入参的url为需要加载的web页面的地址。 + +```ts +import { ExtWeb } from 'WebSceneKitHsp' +... +build() { + Row() { + Column() { + ExtWeb({ url: 'resource://rawfile/frameworkTest_web/pages/index/entry.html' }) + } + .width('100%') + } + .height('100%') +} +``` + +## 3.3 鸿蒙工程编译运行 + +注:DevEco Studio、SDK和 ROM 镜像需要使用5.0的版本 + +1. 将weex工程编译出的web资源拷贝到壳工程的entry/src/main/resources/rawfile目录下 +2. 项目签名 + + ![image](./assets/edb18e95-e129-4e8c-b239-a9ea0a253075.png) +3. 运行entry + + ![image](./assets/e624406a-3c73-40af-85fb-0aa9f07e2909.png) + +# 四、功能开发 + +## 4.1 WebSceneKitHsp + +### 4.1.1 功能简介 + +WebSceneKitHsp为weex框架提供了增强web功能,包括页面管理、跨页面通信、全局监听事件、模版预热、web侧api调用原生api、高性能组件、自定义拓展组件等能力。 + +### 4.1.2 接口说明 + +#### 4.1.2.1 **ExtWeb组件** + +扩展web组件,内部封装了页面管理服务、跨页通信、web实例预热、模版预热等功能。具体参数说明: + +| 名称 | 类型 | 描述 | 是否必选 | +| ---- | ------ | --------- | -------- | +| url | string | 加载的url | Y | + +#### 4.1.2.2 **ExtWebController** + +对外提供的扩展web组件控制类, 具体接口有init、registerCustomFun以及triggerEvent。 + +##### 4.1.2.2.1 init接口 + +动态解析配置文件并初始化web资源实例池。具体参数说明: + +| 名称 | 类型 | 描述 | 是否必选 | +| --------- | ----------------------- | ------------------------- | -------- | +| pathArray | Array[string] | 业务模块根目录 | Y | +| uiContext | UIContext | UI上下文实例UIContext对象 | Y | +| context | common.UIAbilityContext | 上下文context | Y | +| poolSize | number | 初始化web实例资源池数量 | N | + +##### 4.1.2.2.2 registerCustomFun接口 + +注入自定义ArkTs高阶api到WebSceneKit,在weex端即可直接调用。具体参数说明: + +| 名称 | 类型 | 描述 | 是否必选 | +| ------- | -------- | -------------- | -------- | +| funName | string | 注入的方法名称 | Y | +| fun | Function | 注入的方法 | Y | + +##### 4.1.2.2.3 triggerEvent接口 + +为Weex的GlobalEvent提供,可以在weex端自定义事件,在ArkTs端通过triggerEvent接口触发事件。具体参数说明: + +| 名称 | 类型 | 描述 | 是否必选 | +| --------- | -------------- | ------------------ | -------- | +| eventName | string | 自定义事件名 | Y | +| data | Object、string | 触发事件返回的数据 | N | + +##### 4.1.2.2.4 setUA接口 + +为业务方提供自定义设置ua属性接口。 + +| 名称 | 类型 | 描述 | 是否必选 | +| ---- | ------ | -------- | -------- | +| ua | string | 自定义ua | Y | + +##### 4.1.2.2.5 refresh接口 + +提供refresh接口,支持刷新当前url的webview。 + +| 名称 | 类型 | 描述 | 是否必选 | +| ---- | ------ | ----------------- | -------- | +| url | string | 当前需要刷新的url | Y | + +## 4.2 页面管理 + +页面管理服务主要包括全局路由、Navigation页面栈控制以及离线组件上下树管理等。属于ExtWeb的核心模块,具体架构如图所示: + +![image](./assets/54fbe58e-12c3-4b1d-8153-2a08e3357f0c.png) + +页面加载核心流程:初始化web池 -> 页面加载/跳转 -> 查询路由配置 -> 获取web实例 ->获取对应pageStack, push页面栈 -> NodeContainer上下树管理 -> 路由到目标html + +### 4.2.1 方案 + +weex页面可分为以下4种,1、高频访问页面 2、不需要跨页面通信场景的页面 3、有跨页面通讯的页面 4、web和原生混合的页面,页面管理服务对不同的页面进行管理并提供针对性的加载策略。 + +1)针对高频访问的web页面,使用模版预热来提升页面加载速度,模版预热见3.3; + +2)针对不需要跨页面通信场景的web页面,使用web容器共享来减少web实例的创建; + +3)针对需要跨页面通信场景的web页面,使用多web实例进行加载,即一个页面对应一个web实例,当页面跳转后,web实例依然存在; + +4)针对h5和原生的混合页面,如果混合页面跳转的目标页面为混合页面则不触发原生页面的跳转; + +使用以上策略的页面管理服务在保证性能最优的情况下页面跳转和回退符合正常逻辑。 + +### 4.2.2 ExtWeb组件的初始化 + +调用ExtWebController的init接口,初始化ExtWeb组件。init过程会动态解析每个业务模块下的配置文件、初始化web实例资源池, ExtWeb的初始化需要在使用ExtWeb之前。建议在entryAbility的onWindowStageCreate中调用ExtWebController的init方法,参数poolSize最大值为10,大于10默认poolSize等于10。 + +```ts +onWindowStageCreate(windowStage: window.WindowStage) { + // Main window is created, set main page for this ability + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageCreate'); + ExtWebController.setUA(''); + windowStage.loadContent('pages/Index', (err, data) => { + // 支持业务侧动态配置 将业务模块路径传入init 页面配置文件在每个业务模块根目录 + // ExtWebController.init('WebSceneConfig.json', windowStage.getMainWindowSync().getUIContext(), this.context, 10); + ExtWebController.init(['frameworkTest_web'], windowStage.getMainWindowSync().getUIContext(), this.context, 10); + if (err.code) { + hilog.error(0x0000, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? ''); + return; + } + AppStorage.setOrCreate("uiContext", windowStage.getMainWindowSync().getUIContext()); + hilog.info(0x0000, 'testTag', 'Succeeded in loading the content. Data: %{public}s', JSON.stringify(data) ?? ''); + AppStorage.setOrCreate("UIContext", windowStage.getMainWindowSync().getUIContext()); + }); + } +``` + +如果跳转页面过多,web资源池中的空余web耗尽时,会在webSceneKitHsp中动态创建新的web资源。 + +```ts +public getWebInstanceId(reuse: boolean, url?: string): number { + ... + // if the webIdleMap size less than minimumThreshold, new web + if (this.webIdleMap.size <= this.minimumThreshold) { + const currentSize: number = this.webIdleMap.size + this.webUsedMap.size; + this.createNormalWebInstance(this.uiContext as UIContext, currentSize + 1, 2); + } + ... +} +``` + +### 4.2.3 ExtWeb组件的使用 + +对外提供的扩展web组件。可在page页面的容器控件中加载ExtWeb组件,入参的url为首页的url。 + +```ts +build() { + Row() { + Column() { + ExtWeb({ url: this.url }) + } + .width('100%') + } + .height('100%') +} +``` + +### 4.2.4 配置文件说明 + +配置文件需要放在entry模块的rawfile目录下,建议放在每个业务根目录。配置文件中各字段需要按照如下格式定义: + +```markup +└── weexProjects # 所有项目的集合 + ├── projectName # 项目名称,项目是一些html网页按照业务划分的集合,由伙伴定义 + ├── urls # 当前项目下的的url地址和type类型 + │ ├── url # url地址 + │ └── type # 对应的类型,在下文介绍 + └──preLoad # 当前项目需要预加载的项目 +``` + +type类型说明: + +type:1 模板预热类型,适用于高频访问且无白屏场景的页面,快速加载页面,性能持平原生跳转。 +type:2 多页面多web实例,适用于有跨页面通讯场景的页面,支持broadcastChannel和globalEvent; +type:3 多页面单web实例,适用于不需要跨页面通讯的页面,默认类型。 + +type:4 混合页面,有两种情况: 1)加载的web和原生组件在同一个Page页;2)原生page使用多个ExtWeb组件。 + +注:没有配置的页面默认为type2 + +示例代码: + +项目weexProject里的resource://rawfile/frameworkTest_web/pages/index/entry.html, 该url地址不需要支持跨页通信,所以配置为 type:3 + +```json +... +"projectName": "weexProject", +"urls": [ + { + "url": "resource://rawfile/frameworkTest_web/pages/index/entry.html", + "type": 3 + }, + ... +] +... +``` + +项目weexProject里的resource://rawfile/frameworkTest_web/pages/mapTest1/entry.html, 该url地址使用跨页通讯接口(broadcastChannel、globalEvent),所以配置为 type:2 + +```json +"projectName": "weexProject", + "urls": [ + ... + { + "url": "resource://rawfile/frameworkTest_web/pages/mapTest1/entry.html", + "type": 2 + }, + ... + ] +... +``` + +机票项目某些页面是高频触发场景,需要加载无白屏效果,因此在"测试"项目中需要配置preload为"机票",实现预加载机票项目。 + +```json +... +{ + "projectName": "测试", + "urls": [ + { + "url": "https://www.example.com", + "type": 3 + } + ], + "preLoad": [ + "机票" + ] + }, +... +``` + +为了配合预加载机票项目,"机票"项目下高频的url模版需配置为type:1,保证高频场景的页面能快速加载且无白屏效果。 + +```json +... +{ + "projectName": "机票", + "urls": [ + { + "url": "https://www.example.com", + "type": 1 + }, + { + "url": "https://www.example.com", + "type": 3 + }, + { + "url": "https://www.example.com", + "type": 3 + }, + { + "url": "https://www.example.com", + "type": 1 + } + ], +} +... +``` + +## 4.3 模版预热 + +### 4.3.1 方案 + +模板预热可以将重要页面模板(不带参数)预先加载,在跳转时解析url后的拼接参数,通过history.pushState方法将参数传递进去,进行局部渲染。 + +![image](./assets/45a6a96e-2d2e-4ab3-baba-23285224d6dd.png) + +### 4.3.2 路由配置文件 + +首先在路由配置文件中将需要预热的url的type设置为1,并且将该业务模块所依赖的模块配置在preload中。路由配置文件的介绍见[4.2.4](###4.2.4配置文件说明)。 + +```markup +└── weexProjects # 所有项目的集合 + ├── projectName # 项目名称,项目是一些html网页按照业务划分的集合,由伙伴定义 + ├── urls # 当前项目下的的url地址和type类型 + │ ├── url # url地址 + │ └── type # 对应的类型,在下文介绍 + └──preLoad # 当前项目需要预加载的项目 +``` + +### 4.3.3 解析配置文件 + +在EntryAbility.ets调用init方法解析路由配置文件,解析配置文件过程中会读取type为1的所有url。 + +```ts +ExtWebController.init(['web'], windowStage.getMainWindowSync().getUIContext(), this.context, 10); +``` + +首先将每个业务模块下type为1,也就是需要进行预热的url(未带参数)和该模块依赖的其余模块存储在Project类中。并且以模块名为key值,Project类为value。以下实现已封装在webSencekitHsp中。 + +```ts +let projects: Map = new Map(); +public static parseConfig(context: common.UIAbilityContext, path: string): Promise { + return new Promise((resolve, reject) => { + context.resourceManager.getRawFileContent(path).then((data: Uint8Array) => { + let jsonObject = JSON.parse(ParseUtil.bufferToString(data.buffer)) as Record>; + let weexProjects = jsonObject.weexProjects as Array; + weexProjects.forEach((jsonProject: JsonProject) => { + let preloadUrls: Array = new Array(); + // 将模块下所有type为1的url存储在preloadUrls中 + jsonProject.urls.forEach((urlParams: UrlParams) => { + urlConfig.set(urlParams.url, new UrlInfo(urlParams.type, jsonProject.projectName)); + if (urlParams.type === 1) { + preloadUrls.push(urlParams.url); + } + }) + let project: Project = new Project(preloadUrls, jsonProject.preLoad); + projects.set(jsonProject.projectName, project); + }) + + // 如果项目A依赖B,那么B也要依赖A,否则从B回退A,会重新刷新界面 + projects.forEach((value: Project, key: string) => { + value.preLoadProjects.forEach((preLoadProjectName: string) => { + if (!projects.get(preLoadProjectName)?.preLoadProjects.includes(key)) { + projects.get(preLoadProjectName)?.preLoadProjects.push(key); + } + }) + }) + + // 如果项目需要依赖自己 + projects.forEach((value: Project, key: string) => { + if (!value.preLoadProjects.includes(key)) { + value.preLoadProjects.push(key); + } + }) + + RouterStorage.getInstance().urlConfig = urlConfig; + RouterStorage.getInstance().projectsConfig = projects; + resolve() + }).catch((error: BusinessError) => { + ... + }) + }) +} +``` + +### 4.3.4 预热模板 + +将预热url以及依赖项构建完毕后,在页面跳转时根据当前url所在的模块获取所有需要预热的url,执行addProject方法预热模板。以下实现已封装在webSencekitHsp中。 + +```ts +public preloadTemplate(routerUrl: string) { + ... + // 需要预热的模板 + let preLoadProjects: Array | undefined = RouterStorage.getInstance() + .projectsConfig + .get(projectName)?.preLoadProjects; + + // 当前预热的模板 + let currentProjects: Map> = WebManager.getInstance().preloadStatus; + + let addProjects: Array = new Array(); + let deleteProjects: Array = new Array(); + // 获取当前预热模板,如果不包含需要预热模块,则添加进addProjects + preLoadProjects?.forEach((preLoadProject: string) => { + if (!currentProjects.has(preLoadProject)) { + addProjects.push(preLoadProject); + } + }) + currentProjects.forEach((value: Map, key: string) => { + if (!preLoadProjects?.includes(key)) { + deleteProjects.push(key); + } + }) + + if (preLoadProjects?.length === 0 && deleteProjects.length === 0) { + return; + } + + // 删除冗余模版 + WebManager.getInstance().deleteProject(deleteProjects); + + // 预热模版 + WebManager.getInstance().addProject(addProjects); +} +``` + +addProject方法一共做了两件事:1. 遍历需要提前预热的业务模块下的所有url(未带参数),并将url的状态值设置成'initial';2. 为预热url(未带参数)配备一个web实例,执行controller的loadurl。 + +```ts +public async addProject(addProjects: Array) { + let taskUrls: Array = new Array(); + addProjects.forEach((addProjectName: string) => { + let preloadUrls: Array | undefined = RouterStorage.getInstance() + .projectsConfig + .get(addProjectName)?.preloadUrls; + let projectsStatusMap: Map = new Map(); + preloadUrls?.forEach((preloadUrl: string) => { + projectsStatusMap.set(preloadUrl, Constant.STATUS_INITIAL); + taskUrls.push(preloadUrl); + }) + this.preloadStatus.set(addProjectName, projectsStatusMap); + }) + + taskUrls.forEach((url: string) => { + if (this.templateIdleMap.size === 0) { + return; + } + let webId: number = this.templateIdleMap.keys().next().value; + let controller: web_webview.WebviewController | undefined = this.webControllerMap.get(webId); + controller?.clearHistory(); + let builderNode: BuilderNode | undefined = this.templateIdleMap.get(webId); + if (builderNode) { + this.templateUsedMap.set(webId, builderNode); + this.templateIdleMap.delete(webId); + } + this.templateUrlMap.set(url, webId); + url = UrlUtil.addFakeDomain(url); + controller?.loadUrl(url); + }) +} +``` + +在url渲染完成后,执行refreshStatus将url的状态值设置成'finish'。 + +```ts +public refreshStatus(url: string) { + let fakeDomain: string = Constant.FAKE_DOMAIN; + if (url.startsWith(fakeDomain)) { + url = url.substring(fakeDomain.length); + } + let projectName: string = RouterStorage.getInstance().getProjectName(url); + this.preloadStatus.get(projectName)?.set(url, 'finish'); + } +``` + +### 4.3.5 局部刷新 + +预热成功后,在页面跳转时将url(带参数)的拼接参数截取出来执行history.pushState控制业务页面局部刷新,weex工程需要封装pushState监听事件。以下实现已封装在webSencekitHsp中。 + +![image](./assets/b6302f87-2db1-470b-ac09-0f2da0e9374a.png) + +```ts +// GlobalRouter.ets +let params = UrlUtil.getUrlParams(routerUrl); +webManagerInstance.getWebController(webId)?.runJavaScript(`reloadUrl(\"${params}\")`); +if (WebManager.getInstance().isPreloadFinish(routerUrl)) { + PageModelController.getInstance().loading(false); +} +``` + +## 4.4 web侧Api调用系统Api + +部分web侧api需要调用系统api,如获取蓝牙、wifi信息等,以下介绍如何实现从web的api调用到系统的api。 + +### 4.4.1 编译打包 + +weex 模块鸿蒙化是在编译打包过程中对module的导入进行语法树分析,将需要桥接到原生的module转为引用weex-harmony模块,在weex-harmony中通过jsBridge桥接到原生,在鸿蒙原生进行实现。在此过程中需要用户做4步操作 1、添加自定义babel插件 2、babel插件的实现(可直接复用模版) 3、在package.json中引入weex-harmony插件 4、在打包命令中添加ISHARMONY=true + +![image](./assets/a62d1304-0d15-427f-af2f-179dcf7373a6.png) + +#### 4.4.1.1 在babel.config.js文件中添加自定义babel插件 + +此自定义插件的作用是在编译时进行抽象语法树分析,将weex.requireModule转为 `require('@ohos/weex-harmony')` + +```javascript +module.exports = { + plugins: ['./configs/weexTransform.js'] +} +``` + +#### 4.4.1.2 自定义babel插件实现 + +自定义babel插件weexTransform.js文件内容如下,文件路径可自定义,但需要和babel.config.js中配置的路径保持一致 + +```javascript +const weexExtModules = [ + 'weexModule', + 'globalEvent', + 'clipboard', + 'navigator', + 'deviceInfo', + 'websocket', +] + +function isNeedWeexExtProxy(module) { + return (weexExtModules.indexOf(module) === -1) ? false : true; +} + +module.exports = function({ types: t }) { + return { + name: "weexTransform", + visitor: { + StringLiteral(path, state) { + }, + CallExpression(astPath) { + const node = astPath.node + const calleePath = astPath.get('callee') + const callee = calleePath.node + if (callee.type === 'MemberExpression') { + const args = astPath.node.arguments + if ( + args.length === 1 && + t.isStringLiteral(args[0]) && + isNeedWeexExtProxy(args[0].value) && + t.isIdentifier(callee.object) && + callee.object.name === 'weex' + ) { + if (process.env.ISHARMONY === 'true') { + console.log('TestXXX weexTransform.js harmony process.env.ISHARMONY:' + process.env.ISHARMONY); + // callee.object = t.identifier('weexExt') + + const parentPath = astPath.parentPath?.parentPath + const parentNode = parentPath?.node + if (parentNode && t.isVariableDeclaration(parentNode)) { + const key = args[0].value + + const properties = [ + t.objectProperty( + t.identifier(key), + t.identifier(key), + false, + true + ) + ] + const objectPattern = t.objectPattern(properties) + + const requireExpression = t.CallExpression( + t.identifier('require'), + [t.stringLiteral('@ohos/weex-harmony')] + ) + const replaceNode = t.variableDeclaration('const', [ + t.variableDeclarator(objectPattern, requireExpression) + ]) + + parentPath.replaceWith(replaceNode) + } else { + if (parentNode && t.isCallExpression(parentNode)) { + const callee = parentNode.callee + const object = callee.object + const requireModuleName = object.arguments[0].value + + const requireExpression = t.callExpression( + t.identifier('require'), + [t.stringLiteral('@ohos/weex-harmony')] + ) + + const memberExpression = t.memberExpression( + requireExpression, + t.identifier(requireModuleName) + ) + + parentNode.callee.object = memberExpression + } + } + } else { + console.log('TestXXX weexTransform.js not harmony process.env.ISHARMONY:' + process.env.ISHARMONY); + } + } + } + } + } + }; +}; +``` + +#### 4.4.1.3 添加适配层依赖包@ohos/weex-harmony + +weex-harmony插件的作用是适配weex侧的api并桥接到原生调用鸿蒙原生侧的高阶Api,package.json中路径需要修改为本地tgz包文件路径,tgz包生成方式见[3.1.2.1](####3.1.2.1添加鸿蒙化打包命令及项目依赖)。 + +![image](./assets/cb897828-c91b-4c90-ba93-edd725633983.png) + +@ohos/weex-harmony 源码参考: + +```javascript +let weexModule = { + name: "weex扩展API", + // 默认走同步 + // isAsync: 是否异步方式调用 native api + callNative: function (name, paramObj, callback, isAsync = false) { + // @ts-ignore + native.run(name, paramObj, callback, isAsync); + } +} + +let clipboard = { + name: "weex剪贴板事件", + getString: function (callback) { + weexModule.callNative('getString', "", callback); + }, + setString: function (text) { + let paramObj = {"message": text}; + weexModule.callNative('setString', paramObj, undefined); + } +} + +let deviceInfo = { + name: "weex获取全屏高度", + enableFullScreenHeight: function (callback) { + weexModule.callNative('enableFullScreenHeight', null, callback); + } +} + +let navigator = { + name: "weex导航事件", + pop: function (options, callback) { + weexModule.callNative('navigatorPop', options, callback); + }, + push: function (options, callback) { + weexModule.callNative('navigatorPush', options, callback); + }, + replace: function (options, callback) { + weexModule.callNative('navigatorReplace', options, callback); + } +} + +let globalEvent = { + name: "weex监听全局事件", + addEventListener: function (eventName, callback) { + if (callback === undefined) { + console.error("callback is undefined."); + return; + } + + let paramObj = {'eventName': eventName} + weexModule.callNative('addEventListener', paramObj, callback); + }, + removeEventListener: function (eventName) { + let paramObj = {'eventName': eventName} + weexModule.callNative('removeEventListener', paramObj, undefined); + } +} + +let errorHandlers = []; +let closeHandlers = []; +let openHandlers = []; +let messageHandlers = []; +let socket = null; +const WEB_SOCKET_NO_READY = 'WebSocket is not ready' + +// 给error event事件添加一个data属性 +function handleError(handlers, errorMsg) { + const event = new Event('error'); + handlers.forEach(handler => handler(Object.defineProperty(event, 'data', { + value: errorMsg, + enumerable: true, + writable: true + }))); +} + +const websocket = { + WebSocket: function (url, protocols) { + // 重新创建socket对象,初始化socket + if (socket) { + errorHandlers = []; + closeHandlers = []; + openHandlers = []; + messageHandlers = []; + socket = null; + } + socket = new WebSocket(url, protocols !== undefined && protocols !== '' ? protocols : 'wss'); + + socket.onopen = function handleOpen(event) { + openHandlers.forEach(handler => handler(event)); + }; + + socket.onmessage = function handleMessage(event) { + messageHandlers.forEach(handler => handler(event)); + }; + + socket.onclose = function handleClose(event) { + closeHandlers.forEach(handler => handler(event)); + }; + }, + + onopen: function (handler) { + openHandlers.push(handler); + }, + + onmessage: function (handler) { + messageHandlers.push(handler); + }, + + onerror: function (handler) { + errorHandlers.push(handler); + }, + + onclose: function (handler) { + closeHandlers.push(handler); + }, + + send: function (data) { + if (socket != null) { + try { + socket.send(data); + } catch (e) { + handleError(errorHandlers, e.message) + } + } else { + handleError(errorHandlers, WEB_SOCKET_NO_READY) + } + }, + + close: function () { + if (socket != null) { + // socket存在即关闭 + try { + socket.close(); + errorHandlers = []; + closeHandlers = []; + openHandlers = []; + messageHandlers = []; + socket = null + } catch (e) { + handleError(errorHandlers, e.message) + } + } else { + handleError(errorHandlers, WEB_SOCKET_NO_READY) + } + } +} + + +let picker = { + name: "weex 选择器", + pick: function (options, callback) { + weexModule.callNative('pick', { 'options': options }, callback); + }, + pickDate: function (options, callback) { + weexModule.callNative('pickDate', { 'options': options }, callback); + }, + pickTime: function (options, callback) { + weexModule.callNative('pickTime', { 'options': options }, callback); + } +} + +export { + clipboard, + weexModule, + deviceInfo, + navigator, + globalEvent, + websocket, + picker +} + +``` + +#### 4.4.1.4 在打包命令中添加ISHARMONY=true + +此配置会在[4.4.1.2](####4.4.1.2自定义babel插件实现)的babel插件中使用,如下所示: + +```markup +"build:harmony": "cross-env NODE_ENV=harmony apiEnv=prod ISHARMONY=true webpack --env.NODE_ENV=harmony", +``` + +### 4.4.2 自定义拓展模块 + +当前支持如下方法参数格式function (name, paramObj, callback)的自定义拓展module,自定义拓展模块步骤如下: + +参数说明: + +| 名称 | 类型 | 描述 | 是否必选 | +| -------- | -------- | -------- | -------- | +| name | string | 方法名 | Y | +| paramObj | object | 参数 | Y | +| callback | Function | 回调方法 | Y | + +示例代码: + +1、在[4.4.1.2](####4.4.1.2自定义babel插件实现)的babel插件的weexExtModules对象中添加自定义拓展模块名,如weexModule + +```javascript +const weexExtModules = [ + 'weexModule', + 'globalEvent', + 'clipboard', + 'navigator', + 'deviceInfo', + 'websocket', +] +``` + +2、在weex-harmony中实现weexModule,调用native.run(name, paramObj, callback),native对象通过代理和jsBridge桥接到原生 + +```javascript +let weexModule = { + name: "weex扩展API", + callNative: function (name, paramObj, callback) { + // @ts-ignore + native.run(name, paramObj, callback); + } +} +``` + +3、原生侧使用ExtWebController.registerCustomFun()注册自定义拓展模块的方法,可参考ohos包中example目录下的ohos-example项目下entry/src/main/ets/commonadapter目录下的CommonAdapter.ets,其中方法的实现可自定义实现 + +![image](./assets/7c34a3f4-f143-4b66-9081-9ca592675700.png) + +## 4.5 高性能组件 + +部分对性能有要求的组件需要原生组件的支持,以下介绍通过同层渲染将原生组件渲染到web页面上,提高页面渲染性能。 + +### 4.5.1 同层渲染简介 + +weex在android和ios侧提供Component拓展能力,不同于weex在android和ios侧映射到原生,weex鸿蒙化走web路线,因此,提供一种基于同层渲染的拓展组件能力,在web中使用embed标签,在原生侧解析并将对应的原生组件渲染在embed标签处 + +![image](./assets/576798f5-e7e6-42f4-a936-9582505f0acd.png) + +### 4.5.2 web侧自定义拓展组件实现 + +```vue + + + + + +``` + +在拓展组件实现时,1、可以通过vue的watch监听属性的变化,当属性更新时可通知原生进行更新;2、当多个属性同时更新时,可通过nextTick将数据一次传递到原生侧,减少通信次数。 + +embed标签参数说明: + +| 名称 | 类型 | 描述 | 是否必选 | +| ---- | ------ | --------------------- | -------- | +| id | string | 唯一标识id | Y | +| type | string | 类型,需以native/开头 | Y | + +需要传递给原生端的属性和监听函数可通过jsBridge进行传递,其中weexModule.callNative("transferSameLayerArgs", args)已实现,用户不需要自己实现 + +```javascript +transferPropsAndListeners() { + // 原生组件所需的属性和方法,以对象方式传递 + const args = { + componentId: this.embedId, + src: this.src, // 要播放视频的资源地址 + controls: this.controls, // 是否显示播放控件 + muted: this.muted, // 是否静音 + loop: this.loop, + autoPlay: this.autoPlay, + onPlay: this.handleOnPlay, + onPause: this.handleOnPause, + }; + // 调用JSbridge方法,传递属性和监听方法到原生组件 + weexModule.callNative("transferSameLayerArgs", args); +}, +``` + +另外,用户也可以给自定义组件增加实例方法,比如自定义的Lottie组件中,定义了 play等方法,代码示例如下 + +```javascript + + +export default { + name: "HlLottie", + methods: { + play(callback) { + weexModule.callNative('lottieHandle', { + method: 'play', + name: this.embedId, + }, callback) + }, + // 其他方法定义,省略 + }, + // 其他数据定义,省略 +} +``` + +```javascript + +// 使用Lottie组件, entry.vue 文件 + + + + +``` + +示例代码使用 this.$refs.mylottie.play 调用 Lottie 组件中的 play 方法,该方法使用weexModule.callNative("lottieHandle", ...) 访问原生侧的 lottieHandle API。 + +### 4.5.3 添加自定义loader + +自定义拓展组件在android和ios都是以注册的方式,鸿蒙化时自定义拓展组件在web侧进行实现,在编译成鸿蒙产物时,需要引用到所在的文件,因此提供一个自定义loader在打包成鸿蒙产物时进行自动引用 + +1)自定义loader transform-loader.js实现 + +其中componentMap中需要配置自定义组件名和组件所在的文件名,自定义loader的运行需要在编译命令中添加字段ISHARMONY=true,参考[4.4.1.4](####4.4.1.4在打包命令中添加ISHARMONY=true) + +```javascript +const compiler = require('vue-template-compiler') +const parser = require('@babel/parser') +const traverse = require('@babel/traverse').default +const generator = require('@babel/generator').default +const t = require('@babel/types') +const { parse } = require('himalaya') +const path = require('path') + +let currentModulePath = '' + +// 组件引入基路径,baseUrl的值为引入组件路径的公共部分 +const baseUrl = '../src/components/' + +/** + * componentName:该属性的值是导入和注册组件时的组件名称,使用时请遵循Vue组件的命名和使用规范 + * + * componentAddress: 组件所在地址 + * + * isInPlugin: 是否从三方库引入 + */ +const componentMap = [ + { + componentName: 'HlRichtext', + componentAddress: 'hl-richtext-base.vue', + isInPlugin: false + }, + { + componentName: 'HlVideo', + componentAddress: 'hl-video-base.vue', + isInPlugin: false + }, + { + componentName: 'HlLottie', + componentAddress: 'hl-lottie-base.vue', + isInPlugin: false + }, + { + componentName: 'HlWeb', + componentAddress: 'hl-web-base.vue', + isInPlugin: false + }, + { + componentName: 'HlTextarea', + componentAddress: 'hl-textarea-base.vue', + isInPlugin: false + }, + { + componentName: 'HlButton', + componentAddress: 'hl-button-base.vue', + isInPlugin: false + }, + { + componentName: 'HlSlider', + componentAddress: 'hl-slider-base.vue', + isInPlugin: false + } +] +const componentSet = new Set() + +/** + * 判断是否为windows环境 + * @returns + */ +function isWin32(){ + if(process.platform === 'win32') { + return true + } else { + return false + } +} + +/** + * 处理解析标签名,将这种转为HlVideo + * @param {*} tagName + */ +function transformTagName(tagName) { + if(tagName.includes('-')) { + const nameSplit = tagName.split('-') + return nameSplit.join('') + } + return tagName +} + +function hasTargetElement(tagName) { + let hasElement = false + let componentName = '' + componentMap.forEach((item) => { + if(item.componentName.toLowerCase() === transformTagName(tagName)) { + hasElement = true + componentName = item.componentName + } + }) + + return { + hasElement, + componentName + } +} + +/** + * 遍历html节点,将需要引入的组件添加到componentSet中 + * @param {*} node html节点 + */ +function traverseNode(node) { + if (node.type === 'element') { + const {hasElement, componentName} = hasTargetElement(node.tagName) + if (hasElement) { + componentSet.add(componentName) + } + if (node.children) { + node.children.forEach((child) => { + traverseNode(child) + }) + } + } +} + +/** + * 创建import组件导入节点 + * @param {*} componentName 组件名称 + * @returns 导入的ast节点 + */ +function buildImportDeclaration(componentName) { + let isInPlugin = getIsInPlugin(componentName) + return t.importDeclaration( + isInPlugin ? [t.importSpecifier(t.identifier(componentName), t.identifier(componentName), false, true)] : [t.importDefaultSpecifier(t.identifier(componentName))], + t.stringLiteral(getComponentLoc(componentName)) + ) +} + +/** + * 判断当前组件的引入是否是三方库引入 + * @param {*} componentName + */ +function getIsInPlugin(name) { + let isInPlugin = false + componentMap.forEach((item) => { + if(item.componentName === name) { + isInPlugin = item.isInPlugin + } + }) + + return isInPlugin +} + +/** + * 通过组件名称获取组件所在位置 + * @param {*} name 组件名称 + */ +function getComponentLoc(name) { + let address = '' + let isInPlugin = false + componentMap.forEach((item) => { + if(item.componentName === name) { + address = baseUrl + item.componentAddress + isInPlugin = item.isInPlugin + } + }) + + if (isInPlugin) { + return address + } else { + return getAbsPath(address) + } +} + +/** + * 根据引入的路径获取组件导入的路径 + * @param {*} address + * @returns + */ +function getAbsPath(address){ + const componentAbsolute = path.resolve(__dirname, address) + if(isWin32()) { + return path.relative(currentModulePath, componentAbsolute).replace('..\\','').replace(/\\/g,'/') + } else { + return path.relative(currentModulePath, componentAbsolute).replace('../','') + } +} + +/** + * 生产SFC代码 + * @param {*} moduleResoveRet + */ +function generateCode(moduleResoveRet) { + let styleTemplate = '' + let styleAttrs = '' + let scriptAttrs = '' + + moduleResoveRet.styles.forEach((item) => { + styleTemplate += item.content + }) + + Object.keys(moduleResoveRet.script.attrs).forEach((item) => { + if (typeof moduleResoveRet.script.attrs[item] === 'boolean') { + scriptAttrs += ` ${item}` + } else { + scriptAttrs += ` ${item}="${moduleResoveRet.script.attrs[item]}"` + } + }) + + if(moduleResoveRet.styles.length){ + Object.keys(moduleResoveRet.styles[0].attrs).forEach((item) => { + if (typeof moduleResoveRet.styles[0].attrs[item] === 'boolean') { + styleAttrs += ` ${item}` + } else { + styleAttrs += ` ${item}="${moduleResoveRet.styles[0].attrs[item]}"` + } + }) + } + + const template = ` + +${moduleResoveRet.script.content} +${styleTemplate} + ` + return template +} + +/** + * 添加components对象 + * @param {*} data + */ +function addComponentsProperty(data) { + if (componentSet.size !== 0) { + componentSet.forEach((value) => { + if (!data.value.properties.some(item => item.value.name == value)) { + const newProperty = t.objectProperty(t.identifier(value), t.identifier(value),false, true) + data.value.properties.push(newProperty) + } + }) + } +} + +module.exports = function (source) { + if (process.env.ISHARMONY === 'true') { + currentModulePath = this.resourcePath + const moduleResoveRet = compiler.parseComponent(source) + const { template, script, styles } = moduleResoveRet + const tempAst = parse(template.content) + tempAst.forEach((node) => { + traverseNode(node) + }) + + // 单模块中引入了自定义组件 + if (componentSet.size !== 0) { + const scriptAst = parser.parse(script.content, { + sourceType: 'module', + // 在此添加需要解析的插件 + }) + + traverse(scriptAst, { + Program(path) { + componentSet.forEach((componentName) => { + path.unshiftContainer('body', buildImportDeclaration(componentName)) + }) + }, + ExportDefaultDeclaration(path) { + if (componentSet.size !== 0) { + if (t.isObjectExpression(path.node.declaration)) { + const properties = path.node.declaration.properties + const result = properties.find(item => item.key.name == 'components') + if (result) { + addComponentsProperty(result) + } else { + const componentsAst = t.objectProperty(t.identifier('components'), t.objectExpression([])) + properties.push(componentsAst) + addComponentsProperty(componentsAst) + } + } + } + } + }) + + // 清除componentSet中的缓存,准备进入下次循环 + componentSet.clear() + + const { code } = generator(scriptAst) + moduleResoveRet.script.content = code + source = generateCode(moduleResoveRet) + } + } + return source +} +``` + +2)自定义loader注册 + +`loader`配置代码如下: + +```javascript +module.exports = { + module: { + rules: [ + { + test: /\.vue(\?[^?]+)?$/, // 配置解析.vue文件 + use: [ + { + loader: path.resolve(__dirname, 'transform-loader.js'), // 引入自定义loader,transform-loader.js(和配置文件在同一目录) 来解析.vue文件 + } + ], + }, + ] + }, +}; +``` + +因为不同的工程对于`.vue`解析配置的`loader`存在差异,可能存在对`.vue`使用多个`loader`解析的情况,因此在配置自定义`loder`时需要确保自定义`loader`最新执行,因此需要将该`loader`放到数组最后。示例代码如下: + +```javascript +//webpack.common.conf.js +module.exports = { + const webConfig = { + module: { + rules: [ + { + test: /\.vue(\?[^?]+)?$/, + use: [ + { + loader: 'vue-loader', // 使用三方Loader解析.vue文件 + options: { + postcss: [require('autoprefixer')({ browsers: ['last 10 Chrome versions', 'last 5 Firefox versions', 'Safari >= 6', 'ie > 8'] })], + compilerOptions: { + modules: [ + { + postTransformNode: el => { + // to convert vnode for weex components. + require('weex-vue-precompiler')()(el) + } + } + ] + } + } + }, + { + loader: path.resolve(__dirname, 'transform-loader.js'), // 引入自定义loader解析.vue文件 + } + ], + }, + ] + }, + } +}; +``` + +### 4.5.4 原生侧组件的实现 + +原生侧组件可以通过params接收web侧自定义拓展组件传递过来的属性和方法并和自己的属性和方法进行绑定,在web侧还可以通过vue的watch来监听属性,当属性发生变化时立即通知原生侧做对应的更新。以下为原生侧自定义组件示例: + +```javascript +import { sameLayerManager } from 'WebSceneKitHsp/Index'; +import { VideoParams } from '../../interfaces/SameLayer'; + +@Component +export struct NativeVideo { + @ObjectLink params: VideoParams + videoController: VideoController = new VideoController(); + + build() { + Column() { + Video({ + src: this.params.src, + controller: this.videoController + }) + .objectFit(ImageFit.Fill) + .autoPlay(this.params.autoPlay ?? true) + .muted(this.params.muted ?? false) + .loop(this.params.loop ?? false) + .controls(this.params.controls ?? true) + .onClick((event) => { + console.log('NativeEmbed video onClick.') + }) + .onStart(() => { + console.log('NativeEmbed video onPlay.', this.params.height) + const callJsOnPlay: Function | undefined = (sameLayerManager.getSameLayerArgs(this.params.componentId) as VideoParams)?.onPlay + callJsOnPlay && callJsOnPlay('Native Video playing.') + }) + .onPause(() => { + console.log('NativeEmbed video onPause.') + const callJsOnPause: Function | undefined = (sameLayerManager.getSameLayerArgs(this.params.componentId) as VideoParams)?.onPause + callJsOnPause && callJsOnPause('Native Video paused.') + }) + } + .width(this.params.width) + .height(this.params.height) + } +} + +@Builder +export function NativeVideoBuilder(params: VideoParams) { + NativeVideo({ params: params }) + .backgroundColor(Color.Green) +} +``` + +其中VideoParams类型如下: + +```javascript +@Observed +export class VideoParams { + width: number // 组件宽度 + height: number // 组件高度 + componentId: string // 组件ID + src: string // 要播放视频的资源地址 + controls?: boolean // 是否显示播放控件 + muted?: boolean // 是否静音 + loop?: boolean + autoPlay?: boolean + onPlay?: (res?: string) => void + onPause?: (res?: string) => void + + constructor() { + this.width = 0; + this.height = 0; + this.componentId = ''; + this.src = ''; + } +} +``` + +另外,针对Web侧定义的实例方法,比如Lottie的play方法,需要在原生侧定义 lottieHandle API 并注册到通信通道。 + +```javascript +// LottieAPI.ets +import { LottieManager } from '../../samelayer/utils/LottieManager'; + +export class LottieAPI { + lottieHandle(name: string, args: object, successCb: Function, failCb: Function, completeCb: Function) { + const lottieManager = LottieManager.getInstance(); + switch (args['method']) { + case 'play': { + lottieManager.play(args['name'], completeCb); + break; + } + } +} +``` + +注册: + +```javascript +// CommonAdaapter.ets 中进行注册 +export class CommonAdapter { + init() { + //... + ExtWebController.registerCustomFun('lottieHandle', new LottieAPI().lottieHandle) + } +} +``` + +### 4.5.5 原生侧组件注册 + +原生侧定义好需要进行同层渲染的自定义组件后,需要在EntryAbility中使用sameLayerManager的registerNativeComponentBuilders方法进行注册。 + +注意:registerNativeComponentBuilders方法的第一个参数为字符串,需要和web侧自定义拓展组件中embed元素type属性值的“native/”后的字符串保持一致。 + +例如:web侧自定义拓展组件中embed元素的type值为“native/hl-video”,则原生侧注册时使用“hl-video”名称进行注册。 + +```javascript +// 省略... +const ABILITY_TAG = 'EntryAbility'; +const storage = new LocalStorage(); +export default class EntryAbility extends UIAbility { + onCreate(want: Want) { + wbLogger.info(ABILITY_TAG, '%{public}s', 'Ability onCreate'); + storage.setOrCreate('want', want); + GlobalThis.getInstance().setRawFile('spa') + LocalUpdateManagerInstance.updateMiniOnLaunch(this.context) + sameLayerManager.registerNativeComponentBuilders('hl-video', NativeVideoBuilder) + // 省略... + } +``` + +## 4.6 Weex组件属性及事件插件 + +#### 插件背景 + +因为weex鸿蒙化走的是web路线,并坚持尽量不改动weex框架代码。但是这种情况下会暴露一些问题,例如weex中有些组件其属性或事件在h5端不支持,因此为了让客户业务能够使用这些属性及事件,因此我们提供了gesture-loader.js和registerGesture.js配合使用来支持的组件属性进行解析并自己实现一套在h5上运行的属性解决方案。该插件可以从ohos/example/weex-example/configs下获取。gesture-loader.js的主要能力是对vue模块解析,感知元素当中绑定了哪些指定事件和属性,将该事件和属性生成对应的数据结构交给registerGesture.js文件去具体实现,本质上gesture-loader.js只解析不做具体功能实现,registerGesture.js只做方法属性的实现封装。 + +### gesture-loader.js + +#### 主要功能 + +目前gesture-loader.js提供的功能有:**通用事件解析、手势事件解析、weex组件属性及方法解析、vue三段式结构解析**。 + +1、**通用事件解析** + +目前gesture-loader支持这些weex通用事件longpress、appear、disappear、viewAppear、viewDisappear 的解析 + +2、**手势事件解析** + +目前gesture-loader支持对 touchstart、touchmove、touchend、stopPropagation、panstart、panstart、panend、horizontalpan、verticalpan、swipe、LongPress 这10个手势事件的解析 + +3、**weex组件属性及方法解析** + +1)解析组件方法需要在EVENT_MAP数组中添加需要解析的方法名 + +```javascript +// 需要检测的事件 +const EVENTS_MAP = [ + '@touchstart', + '@touchmove', + '@touchend', + '@stopPropagation', + '@panstart', + '@panmove', + '@panend', + '@horizontalpan', + '@verticalpan', + '@swipe', + '@longpress', + '@viewappear', + '@viewdisappear', + '@keyboard', +] +``` + +2)解析组件属性需要在ATTRS_MAP数组中添加需要解析的属性名 + +```javascript +// 需要检测的属性名 +/** + * 这里解析的是属性,针对于属性写法有两中例如 :paging-enabled 和 paging-enabled + * 为了方便解析,在MAP中统一去掉冒号。同时在registerGesture.js文件中的gestureMap中也统一去除冒号 + */ +const ATTRS_MAP = [ + 'show-scrollbar', +] +``` + +但是对于一些特殊的属性解析,需要单独实现而不是放到map数组中,例如paging-enabled属性。该属性是list组件中的属性,因为weex并没有在h5上实现这个属性,因此我们需要对该属性进行适配实现。该属性的作用是让List组件呈现item的形式不再是滑动,而是类似于抖音视频那种,单个cell整体上下移动,该移动是一个动画。针对于这种复杂的属性,在解析的时候需对list组件添加一定的style样式,因此该属性的解析和html结构更改是一起进行的,因此无法将paging-enabled的解析放到ATTRS_MAP数组中,因为该属性的解析涉及到对应组件结构的更改。 + +因此如果一个属性的解析需要对结构进行更改,该属性最好单独解析而不是放到ATTRS_MAP数组中。 + +4、**vue三段式结构解析** + +该loader主要解析.vue文件,并且针对于`