Compare commits

..

29 Commits

Author SHA1 Message Date
4cb3badb4d array demo 2024-09-25 19:23:07 +08:00
9010489037 add convert 2024-09-13 10:18:33 +08:00
3a4338c99a add rest api 2024-09-11 19:27:24 +08:00
ed6cbec7c9 update scheme open alipay 2024-09-11 15:09:21 +08:00
7bd741a8a0 add location helper 2024-09-06 17:35:31 +08:00
15223b7de4 add location helper 2024-09-06 17:05:31 +08:00
7f9c4bc663 fix warning 2024-09-06 15:36:19 +08:00
bdfab3ab29 add location 2024-09-05 20:34:48 +08:00
ff8c5714d9 ini myapp and review rest api 2024-08-27 19:11:26 +08:00
58ee459459 添加设置语言demo,优化逻辑 2024-08-26 17:05:01 +08:00
f30b7036d6 添加设置语言demo 2024-08-26 16:54:34 +08:00
1654669845 修复编译脚本,支持编译 x86 和 arm 2024-07-15 15:09:09 +08:00
0cfbbb8065 增加Res 类 2024-07-05 14:27:49 +08:00
c0c8d90c4f 去除首页调用~ 2024-06-26 15:57:56 +08:00
6e569b3ef5 fix cpp 调用 2024-06-26 15:57:27 +08:00
472fc2e574 fix cpp 2024-06-25 20:46:40 +08:00
d303942188 优化构建脚本 2024-06-25 15:00:04 +08:00
b3eb012942 修改描述 2024-06-24 17:25:40 +08:00
zhangyazhou
b688e11f93 删除不必要的文件 2024-06-24 17:14:14 +08:00
793324640e 增加文件选择 2024-06-24 17:09:46 +08:00
1d6e5653c3 更新使用 5.0 ide 2024-06-24 16:45:01 +08:00
1b925cf8fe 更新开发工具以及 readme 2024-06-17 10:46:16 +08:00
bab53c5e9f 修复资源无法找到的问题 2024-06-03 17:56:47 +08:00
94812592c2 代码调整 2024-06-03 11:57:34 +08:00
172581dff7 添加loading 动画
fix web跳转
2024-05-31 14:05:54 +08:00
e55bf2535c 添加loading 动画 2024-05-31 11:23:33 +08:00
b58e726004 添加x86_64 架构 2024-05-28 20:19:56 +08:00
5b47699894 调整构建脚本 2024-05-28 20:06:18 +08:00
500ff1073e 调整C++ 代码 2024-05-28 20:05:06 +08:00
89 changed files with 1324 additions and 431 deletions

1
.gitignore vendored
View File

@@ -11,3 +11,4 @@
**/.test **/.test
oh-package-lock.json5 oh-package-lock.json5
/oh-package-lock.json5 /oh-package-lock.json5
**/**/.preview

View File

@@ -2,7 +2,7 @@
"string": [ "string": [
{ {
"name": "app_name", "name": "app_name",
"value": "HM4Demo" "value": "HMDemo"
} }
] ]
} }

View File

@@ -9,7 +9,7 @@
"@devwiki/common_ui": "file:../common_ui", "@devwiki/common_ui": "file:../common_ui",
"@devwiki/base": "file:../base", "@devwiki/base": "file:../base",
"@ohos/axios": "^2.2.0", "@ohos/axios": "^2.2.0",
"@devwiki/native_lib": "file:../native_lib" "@devwiki/hmcalculate": "file:../hmcalculate"
}, },
"devDependencies": {}, "devDependencies": {},
"dynamicDependencies": {} "dynamicDependencies": {}

View File

@@ -0,0 +1,22 @@
import { AbilityConstant, AbilityStage, Configuration, Want } from '@kit.AbilityKit';
const TAG = '[AbilityStage]';
export default class AppAbilityStage extends AbilityStage {
onCreate(): void {
console.log(TAG, "onCreate")
}
// onAcceptWant(want: Want): string {
// }
// onNewProcessRequest(want: Want): string {
// }
onConfigurationUpdate(newConfig: Configuration): void {
}
onMemoryLevel(level: AbilityConstant.MemoryLevel): void {
}
}

View File

@@ -0,0 +1,43 @@
import { Context } from '@ohos.arkui.UIContext';
import { window } from '@kit.ArkUI';
import { abilityAccessCtrl } from '@kit.AbilityKit';
import { Log } from '@devwiki/base';
import { BusinessError } from '@kit.BasicServicesKit';
const TAG = '[MyApp]'
export class MyApp {
static appContext: Context;
static uiContext: UIContext;
static mainWindow: window.Window;
static uiAbilityContext: Context;
private constructor() {
}
static initAbility(uiAbilityContext: Context) {
MyApp.uiAbilityContext = uiAbilityContext;
MyApp.appContext = uiAbilityContext.getApplicationContext();
}
static initWindow(window: window.Window) {
MyApp.mainWindow = window;
MyApp.uiContext = window.getUIContext();
}
static requestBasicPermission() {
let atManager = abilityAccessCtrl.createAtManager();
try {
atManager.requestPermissionsFromUser(MyApp.uiAbilityContext,
['ohos.permission.INTERNET'])
.then((data) => {
Log.info(TAG, 'requestBasicPermission, data:' + data.permissions[0])
})
.catch((err: BusinessError) => {
Log.info(TAG, 'requestBasicPermission, error:' + err.message)
})
} catch (err) {
}
}
}

View File

@@ -1,6 +1,9 @@
import { AbilityConstant, UIAbility, Want } from '@kit.AbilityKit'; import { AbilityConstant, UIAbility, Want } from '@kit.AbilityKit';
import { hilog } from '@kit.PerformanceAnalysisKit'; import { hilog } from '@kit.PerformanceAnalysisKit';
import { window } from '@kit.ArkUI'; import { window } from '@kit.ArkUI';
import { MyApp } from '../MyApp';
const TAG = '[AppAbility]'
export default class AppAbility extends UIAbility { export default class AppAbility extends UIAbility {
constructor() { constructor() {
@@ -10,24 +13,26 @@ export default class AppAbility extends UIAbility {
onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void { onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onCreate'); hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onCreate');
MyApp.initAbility(this.context);
MyApp.requestBasicPermission();
} }
onDestroy(): void { onDestroy(): void {
hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onDestroy'); hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onDestroy');
} }
onWindowStageCreate(windowStage: window.WindowStage): void { onWindowStageCreate(windowStage: window.WindowStage): void {
// Main window is created, set main page for this ability // Main window is created, set main page for this ability
hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageCreate'); hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageCreate');
windowStage.loadContent('pages/Index', (err, data) => { windowStage.loadContent('pages/Index', (err, data) => {
if (err.code) { if (err.code) {
hilog.error(0x0000, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? ''); hilog.error(0x0000, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? '');
return; return;
} }
MyApp.initWindow(windowStage.getMainWindowSync());
hilog.info(0x0000, 'testTag', 'Succeeded in loading the content. Data: %{public}s', JSON.stringify(data) ?? ''); hilog.info(0x0000, 'testTag', 'Succeeded in loading the content. Data: %{public}s', JSON.stringify(data) ?? '');
}); });
} }
onWindowStageDestroy(): void { onWindowStageDestroy(): void {
// Main window is destroyed, release UI related resources // Main window is destroyed, release UI related resources

View File

@@ -1,5 +1,4 @@
import { CommonRes, TitleBar } from '@devwiki/common_ui'; import { CommonRes, TitleBar } from '@devwiki/common_ui';
import web_webview from '@ohos.web.webview';
import { TitleBarMenuType } from '@devwiki/common_ui'; import { TitleBarMenuType } from '@devwiki/common_ui';
import { router, window } from '@kit.ArkUI'; import { router, window } from '@kit.ArkUI';
import promptAction from '@ohos.promptAction'; import promptAction from '@ohos.promptAction';
@@ -7,9 +6,11 @@ import { BusinessError } from '@ohos.base';
import { Log } from '@devwiki/base'; import { Log } from '@devwiki/base';
import { BaseLocalStorage, ScreenUtil } from '@devwiki/base'; import { BaseLocalStorage, ScreenUtil } from '@devwiki/base';
import { HomeItem, HomeItemGroup } from '../model/Home'; import { HomeItem, HomeItemGroup } from '../model/Home';
import { common, Want } from '@kit.AbilityKit'; import { MyApp } from '../MyApp';
import { CalculateAdapter } from '@devwiki/native_lib/src/main/cpp/types/libnatvie_lib';
import './animation/LoadingPage'
import './animation/ScaleRotatePage'
import { PageName } from './PageName';
@Entry @Entry
@Component @Component
@@ -29,7 +30,9 @@ struct Index {
{ {
name: 'Component', name: 'Component',
items: [ items: [
{name: 'InputPage', page: 'pages/component/InputPage'} {name: 'InputPage', page: 'pages/component/InputPage'},
{name: 'ToastPage', page: 'pages/component/ToastPage'},
{name: 'TextPage', page: 'pages/component/TextPage'}
] ]
}, },
// 布局 // 布局
@@ -45,6 +48,8 @@ struct Index {
name: "Animation", name: "Animation",
items: [ items: [
{ name: 'CompTransition', page: 'pages/animation/CompTransitionPage'}, { name: 'CompTransition', page: 'pages/animation/CompTransitionPage'},
{ name: 'Loading', page: 'pages/animation/LoadingPage'},
{ name: 'ScaleRotatePage', page: PageName.ScaleRotatePage },
] ]
}, },
// 多媒体 // 多媒体
@@ -59,18 +64,22 @@ struct Index {
name: 'System', name: 'System',
items: [ items: [
{name: "Scheme", page: 'pages/system/SchemePage'}, {name: "Scheme", page: 'pages/system/SchemePage'},
{name: "MVVM", page: 'pages/mvvm/HomePage'} {name: "MVVM", page: 'pages/mvvm/HomePage'},
{name: "ArrayBind", page: 'pages/mvvm/ArrayBindPage'},
{name: "SetLanguage", page: 'pages/system/SetLanguagePage'}
]
},
{
name: 'Map',
items: [
{name: 'Map', page: 'pages/map/MapPage'}
] ]
} }
]; ];
adapter?: CalculateAdapter;
aboutToAppear(): void { aboutToAppear(): void {
ScreenUtil.getInstance().initScreenSize(); ScreenUtil.getInstance().initScreenSize(MyApp.appContext);
BaseLocalStorage.getInstance().init(getContext(this)); BaseLocalStorage.getInstance().init(MyApp.appContext);
this.adapter = new CalculateAdapter();
let a = this.adapter.add(1,2);
} }
onPageShow(): void { onPageShow(): void {
@@ -108,17 +117,17 @@ struct Index {
}).then((result: promptAction.ShowDialogSuccessResponse) => { }).then((result: promptAction.ShowDialogSuccessResponse) => {
if (result.index === 0) { if (result.index === 0) {
// 用户点击了“取消”按钮 // 用户点击了“取消”按钮
Log.i('User canceled the operation.'); Log.info('User canceled the operation.');
} else if (result.index === 1) { } else if (result.index === 1) {
// 用户点击了“确认”按钮 // 用户点击了“确认”按钮
Log.i('User confirmed the operation.'); Log.info('User confirmed the operation.');
// 调用router.back()方法,返回上一个页面 // 调用router.back()方法,返回上一个页面
router.back(); router.back();
} }
}).catch((err: Error) => { }).catch((err: Error) => {
let message = (err as BusinessError).message let message = (err as BusinessError).message
let code = (err as BusinessError).code let code = (err as BusinessError).code
Log.i(`Invoke showDialog failed, code is ${code}, message is ${message}`); Log.info(`Invoke showDialog failed, code is ${code}, message is ${message}`);
}) })
return true; return true;
} }
@@ -145,7 +154,11 @@ struct Index {
Divider().margin({ top: 2 }); Divider().margin({ top: 2 });
}.onClick(() => { }.onClick(() => {
if (item.page) { if (item.page) {
if (item.page.startsWith('pages/')) {
this.getUIContext().getRouter().pushUrl({url: item.page }) this.getUIContext().getRouter().pushUrl({url: item.page })
} else {
this.getUIContext().getRouter().pushNamedRoute({name: item.page })
}
} }
}) })
} }
@@ -168,7 +181,7 @@ struct Index {
}) })
} }
}) })
}.width('100%').margin({top: 16, bottom: 48}) }.width('100%').margin({top: 16}).layoutWeight(1)
}.width('100%').height('100%') }.width('100%').height('100%')
} }
} }

View File

@@ -0,0 +1,5 @@
export enum PageName {
ScaleRotatePage = 'animation/ScaleRotatePage'
}

View File

@@ -0,0 +1,40 @@
import { CommonRes } from '@devwiki/common_ui/Index';
import { PageName } from '../../utils/PageRouter';
import { curves } from '@kit.ArkUI';
@Entry({ routeName: PageName.loadingPage })
@Component
struct LoadingPage {
@State animate: boolean = false;
@State rotateValue: number = 0;
@Prop @Watch('onVisibleChanged')visible: boolean = false;
onVisibleChanged() {
if (this.visible) {
this.animate = true;
// 组件一的rotate属性发生变化所以会给组件一添加rotate旋转动画
this.rotateValue = this.animate ? 360 : 0;
}else {
this.animate = false;
}
}
build() {
Column() {
Image(CommonRes.getImage('ic_loading'))
.rotate({ angle: this.rotateValue })
.width(32).height(32).fillColor('#2196F3')
.animation({
curve: curves.initCurve(Curve.Linear),
playMode: PlayMode.Normal,
iterations: -1,
duration: 1000
}).visibility(this.visible ? Visibility.Visible : Visibility.None)
Button('change').width('60%').height(36).onClick(() =>{
this.visible = !this.visible;
}).margin({top: 24})
}.width('100%').height('100%').justifyContent(FlexAlign.Center)
}
}

View File

@@ -0,0 +1,67 @@
import { PageName } from '../PageName';
@Component
@Entry({routeName: PageName.ScaleRotatePage})
struct ScaleRotatePage {
@State orderId:string = ''
@State rootJustifyContent: FlexAlign = FlexAlign.Start
@State showQRAnimation: boolean= false
@State qrColumnHeight: Length = ''
@State qrJustifyContent: FlexAlign = FlexAlign.Start
@State showBarcodeAnimation : boolean = false;
@State barcodeHeight: Length = ''
@State barcodeAngle: number = 0
@Builder
ScanBarCodeDialog(){
}
private ScanBarCodeDialogController: CustomDialogController = new CustomDialogController({
builder: this.ScanBarCodeDialog,
autoCancel: true,
alignment: DialogAlignment.Center,
customStyle: true,
openAnimation: {
}
})
build() {
Column(){
Text('Title')
Column(){
Image($r('app.media.ic_eye_off')).width(200).height(200).onClick(() =>{
})
Text('Order Id:' + this.orderId).visibility(this.showQRAnimation ? Visibility.Visible : Visibility.None)
}.width('100%').visibility(this.showBarcodeAnimation ? Visibility.None : Visibility.Visible)
.animation({
duration: 1000
})
Text('Order Id:' + this.orderId).visibility(this.showQRAnimation || this.showBarcodeAnimation ? Visibility.None : Visibility.Visible)
Column(){
Text('Order Id:' + this.orderId).visibility(this.showBarcodeAnimation ? Visibility.Visible : Visibility.None)
Image($r('app.media.ic_eye_off')).width(400).height(100).onClick(() =>{
})
}.visibility(this.showQRAnimation ? Visibility.None : Visibility.Visible)
.rotate({ centerX: '50%', centerY: '50%', angle: this.barcodeAngle})
.animation({
duration: 1000
})
}.width('100%').height('100%').alignItems(HorizontalAlign.Center).justifyContent(this.rootJustifyContent)
}
}

View File

@@ -2,7 +2,7 @@ import { CommonRes } from '@devwiki/common_ui/Index'
@Entry @Entry
@Component @Component
export struct SVGPage { struct SVGPage {
build() { build() {
Column() { Column() {
Text().width(96).height(96).backgroundColor($r('app.media.ic_eye_off')) Text().width(96).height(96).backgroundColor($r('app.media.ic_eye_off'))

View File

@@ -3,6 +3,27 @@
@Component @Component
struct TextPage { struct TextPage {
@State states: string[] = ['1', '2', '3', '4'];
build() { build() {
Column(){
Button('Change').onClick(() => {
this.states[3] = '999'
})
List(){
ForEach(this.states, (state: string, index: number) => {
ListItem(){
Column(){
Text(state).width(this.getWidth(state, index))
Divider().width('90%')
}
}
})
}.height('100%').width('100')
}.width('100%')
}
getWidth(title: string, index: number): Length {
return 0;
} }
} }

View File

@@ -0,0 +1,41 @@
import { Toast } from '@devwiki/common_ui/'
@Observed
class ToastViewMode {
showToast?: (msg: ResourceStr) => void;
showHint(msg: ResourceStr) {
this.showToast?.(msg);
}
}
@Entry
@Component
struct ToastPage {
@Provide toastVM: ToastViewMode = new ToastViewMode();
aboutToAppear(): void {
this.toastVM.showToast = (msg: ResourceStr) => {
Toast.showToast(msg, true);
}
}
build() {
Column(){
Button("ShowDefault").width('80%').height(36).onClick(() =>{
Toast.showToast("Test Default")
})
Button("ShowTopmost").width('80%').height(36).onClick(() =>{
Toast.showToast("Test Topmost", true)
}).margin({ top: 16 })
Button("VM Show").width('80%').height(36).onClick(() =>{
this.toastVM.showHint("test vm Show")
}).margin({ top: 16 })
}.height('100%').width('100%').justifyContent(FlexAlign.Center)
}
}

View File

@@ -3,7 +3,7 @@ import { ComponentConst } from '@devwiki/common_ui/Index'
@Entry @Entry
@Component @Component
export struct RelativeContainerPage { struct RelativeContainerPage {
build() { build() {
RelativeContainer() { RelativeContainer() {
@@ -12,7 +12,7 @@ export struct RelativeContainerPage {
top: { anchor: ComponentConst.ContainerId, align: VerticalAlign.Top }, top: { anchor: ComponentConst.ContainerId, align: VerticalAlign.Top },
left: { anchor: ComponentConst.ContainerId, align: HorizontalAlign.Start }, left: { anchor: ComponentConst.ContainerId, align: HorizontalAlign.Start },
bottom: { anchor: ComponentConst.ContainerId, align: VerticalAlign.Bottom } bottom: { anchor: ComponentConst.ContainerId, align: VerticalAlign.Bottom }
}).id('left_menu') }).id('left_menu0')
Button(){ Button(){
Text("2222").height(64) Text("2222").height(64)
@@ -21,7 +21,7 @@ export struct RelativeContainerPage {
top: { anchor: ComponentConst.ContainerId, align: VerticalAlign.Top }, top: { anchor: ComponentConst.ContainerId, align: VerticalAlign.Top },
right: { anchor: ComponentConst.ContainerId, align: HorizontalAlign.End }, right: { anchor: ComponentConst.ContainerId, align: HorizontalAlign.End },
bottom: { anchor: ComponentConst.ContainerId, align: VerticalAlign.Bottom } bottom: { anchor: ComponentConst.ContainerId, align: VerticalAlign.Bottom }
}).id('right_menu') }).id('right_menu0')
}.height(64).width('100%').backgroundColor(Color.Red) }.height(64).width('100%').backgroundColor(Color.Red)
} }
} }

View File

@@ -0,0 +1,58 @@
import { abilityAccessCtrl, bundleManager, common, PermissionRequestResult, Permissions } from '@kit.AbilityKit';
import { geoLocationManager } from '@kit.LocationKit';
import { BusinessError } from '@kit.BasicServicesKit';
import { LocationHelper } from '../../utils/LocationHelper';
@Component
@Entry({routeName: 'MapPage'})
struct MapPage {
@State isShowLocationPopup: boolean = false
appName: string = ''
@State isLocationPermission: boolean = false;
@State locText: string = ''
locationHelper: LocationHelper = new LocationHelper(getContext(this) as common.UIAbilityContext);
@Builder
locationViewBuilder() {
Row() {
Text('开启定位权限').fontSize(15);
Button('去开启')
.type(ButtonType.Normal)
.height(24)
.borderRadius(12)
.width(60)
.backgroundColor(Color.Red)
.onClick(() => {
this.locationHelper.getLocationAddress( 31.12, 121.11, 1, (error: BusinessError, data: geoLocationManager.GeoAddress[]) => {
})
})
SymbolGlyph($r('sys.symbol.xmark')).width(24).height(24).borderRadius(12).onClick(() => {
this.isShowLocationPopup = false;
})
}
.height(40)
.alignItems(VerticalAlign.Center)
.padding(5)
.position({ x: 7, y: 50 })
.zIndex(999)
.backgroundColor('#123333')
.borderRadius(10)
.opacity(0.7)
}
build() {
Column(){
this.locationViewBuilder();
Text(this.locText);
}.width('100%').height('100%')
}
aboutToAppear(): void {
this.locationHelper.requestPermissionsFromUser((allowScope: boolean, allowPrecision: boolean) => {
})
}
}

View File

@@ -137,7 +137,7 @@ async function release() {
@Entry @Entry
@Component @Component
export struct AudioPlayerPage { struct AudioPlayerPage {
build() { build() {
} }

View File

@@ -0,0 +1,25 @@
@Entry
@Component
export struct ArrayBindPage {
@State firstDatas: string[] = ["1"];
@State secondDatas: string[] = ["2"]
build() {
Column(){
Text(this.firstDatas[0]);
Text(this.secondDatas[0]).margin({top: 16})
Button("Change").margin({top: 16}).onClick(() => {
let first = this.firstDatas;
this.changeFirstIndex(first);
this.changeFirstIndex(this.secondDatas);
})
}.width('100%').height('100%')
}
changeFirstIndex(datas: string[]) {
datas[0] = '111'
}
}

View File

@@ -1,9 +1,9 @@
import { Emitter, EmitterItem } from '@devwiki/base'; import { Emitter, EmitterItem } from '@devwiki/base';
import { Toast } from '../../utils/Toast'; import { Toast } from '@devwiki/common_ui';
@Entry @Entry
@Component @Component
export struct HomePage { struct HomePage {
@Provide tv1ViewModel: TabView1ViewModel = new TabView1ViewModel(); @Provide tv1ViewModel: TabView1ViewModel = new TabView1ViewModel();
@Provide tv2ViewModel: TabView2ViewModel = new TabView2ViewModel(); @Provide tv2ViewModel: TabView2ViewModel = new TabView2ViewModel();

View File

@@ -0,0 +1,45 @@
import { BusinessError } from '@ohos.base';
export class APIQuery extends Map<string, string|number|boolean> { }
export interface APIHeader {
[key: string]: string;
}
export enum APIRequestMethod {
GET, POST, PUT, DELETE
}
export class APIRequest {
url: string = "";
method: APIRequestMethod = APIRequestMethod.POST;
extraData?: string | Object | ArrayBuffer;
header?: APIHeader[];
}
export class APIResult<T> {
httpCode: number;
businessError?: BusinessError;
error?: APIError;
data?: T;
}
export interface APIError{
errors: string[];
message: string;
url: string;
}
export interface Organization {
id: number;
name: string;
full_name: string;
email: string;
avatar_url: string;
description: string;
website: string;
location: string;
visibility: string;
repo_admin_change_team_access: boolean;
username: string;
}

View File

@@ -0,0 +1,123 @@
import http from '@ohos.net.http';
import { Log } from '@devwiki/base/Index';
import { APIError, APIHeader, APIQuery, APIRequestMethod, Organization } from './APIModel';
import { APIRequest } from './APIModel';
import { APIResult } from './APIModel';
import axios from '@ohos/axios';
import { Axios } from '@ohos/axios';
const TAG = '[RestAPI]'
export class RestAPI {
private baseUrl: string ='https://gitea.com/api/v1';
private readonly timeout = 10000;
private baseQuery: string = '?=0';
private defaultHeaders: APIHeader[] = [
{ "connection" : "keep-alive" },
{ 'accept-encoding' : 'gzip, deflate, br, zstd' },
{ 'accept-language' : 'zh-CN,zh;q=0.9,en;q=0.8' }
];
public getAllOrganizations(callback: (result: APIResult<Organization[]>) => void) {
let path = '/orgs'
let url = this.getUrl(path);
Log.info(TAG, 'getOrgByName url:' + url);
this.request({
url: url,
method: APIRequestMethod.GET
}, callback);
}
public getAllOrganizationsByPage(page: number, limit: number, callback: (result: APIResult<Organization[]>) => void) {
let path = '/orgs'
let extraQuery = new APIQuery()
extraQuery.set('page', page);
extraQuery.set('limit', limit);
let url = this.getUrl(path, extraQuery);
Log.info(TAG, 'getOrgByName url:' + url);
this.request({
url: url,
method: APIRequestMethod.GET
}, callback);
}
public getOrgByName(name: string, callback: (result: APIResult<Organization>) => void) {
let path = `/orgs/${name}`;
let url = this.getUrl(path);
Log.info(TAG, 'getOrgByName url:' + url);
this.request({
url: url,
method: APIRequestMethod.GET
}, callback);
}
request<T>(apiReq: APIRequest, callback: (result: APIResult<T>) => void) {
Log.info(TAG, 'request, url:' + apiReq.url)
let httpRequest = http.createHttp();
let option:http.HttpRequestOptions = this.createHttpRequestOption(apiReq);
httpRequest.request(apiReq.url, option, (error, resp) =>{
let result: APIResult<T> = new APIResult();
if (!error) {
Log.info(TAG, 'result, httpCode:' + result.httpCode + ', data:' + resp.result?.toString())
result.httpCode = resp.responseCode;
try {
if (resp.responseCode == http.ResponseCode.OK) {
result.data = JSON.parse(resp.result?.toString()) as T
} else {
result.error = JSON.parse(resp.result?.toString()) as APIError;
}
} catch (e) {
Log.error(TAG, 'result json parse error:' + e)
}
callback?.(result);
} else {
result.businessError = error;
callback?.(result);
Log.error(TAG, `request ${apiReq.url} failed, code:${error.code}, message:${error.message}`)
}
httpRequest.destroy();
});
}
private createHttpRequestOption(apiReq: APIRequest): http.HttpRequestOptions{
let headers: APIHeader[] = this.defaultHeaders;
if (apiReq.header) {
apiReq.header.forEach((header) =>{
headers.push(header);
})
}
let method: http.RequestMethod = http.RequestMethod.GET;
if (apiReq.method == APIRequestMethod.POST) {
method = http.RequestMethod.POST;
} else if (apiReq.method == APIRequestMethod.PUT) {
method = http.RequestMethod.PUT;
} else if (apiReq.method == APIRequestMethod.DELETE) {
method = http.RequestMethod.DELETE;
} else {
method = http.RequestMethod.GET;
}
return {
method: method,
extraData : apiReq.extraData,
readTimeout : this.timeout,
connectTimeout: this.timeout,
expectDataType: http.HttpDataType.STRING,
header: headers,
usingProtocol: http.HttpProtocol.HTTP1_1
};
}
private getUrl(path: string, extraQuery?: APIQuery): string {
let url = `${this.baseUrl}${path}${this.baseQuery}`;
if (extraQuery) {
for (let key of extraQuery.keys()) {
url += `&${key}=${extraQuery.get(key)}`
}
}
Log.debug(TAG, `get url, path: ${path}, url:${url}`)
return url;
}
}

View File

@@ -1,44 +1,95 @@
import { Log } from '@devwiki/base/Index'; import { Log } from '@devwiki/base/Index';
import axios, { AxiosError, AxiosResponse } from '@ohos/axios' import axios, { AxiosError, AxiosResponse } from '@ohos/axios'
import http from '@ohos.net.http';
import { RestAPI } from './RestAPI';
import { Organization } from './APIModel';
import { convertxml, util } from '@kit.ArkTS';
const TAG = '[RestAPIPage]'
@Entry({routeName: "RestAPIPage"}) @Entry({routeName: "RestAPIPage"})
@Component @Component
export struct RestAPIPage { struct RestAPIPage {
@State viewModel: RestAPIViewModel = new RestAPIViewModel(); @State viewModel: RestAPIViewModel = new RestAPIViewModel();
build() { build() {
Row() { Column() {
Flex({ Flex({
justifyContent: FlexAlign.SpaceBetween justifyContent: FlexAlign.Start,
direction: FlexDirection.Column,
alignItems: ItemAlign.Center
}) { }) {
Button("Get").onClick(() =>{
this.viewModel.getServerVersion(); Refresh({
refreshing: $$this.viewModel.refreshing,
}){
List(){
ForEach(this.viewModel.orsg, (org: Organization, index: number) =>{
ListItem(){
Row() {
Image(org.avatar_url).width(36).height(36).objectFit(ImageFit.Contain)
Text(org.name)
}.justifyContent(FlexAlign.Start).alignItems(VerticalAlign.Center).height(48)
}
})
}.width('100%').height('100%').layoutWeight(1)
}.pullToRefresh(true)
.onRefreshing(() =>{
this.viewModel.getAllOrgs();
}) })
Text(this.viewModel.serverVersion).backgroundColor(Color.Blue).flexGrow(1); Button("GetByHttp").onClick(() =>{
} this.viewModel.getServerVersionByHttp();
}.justifyContent(FlexAlign.Start).alignItems(VerticalAlign.Center).width('80%').backgroundColor(Color.Green) }).margin({top: 20})
}.width('80%')
}.width('100%')
} }
} }
class RestAPIViewModel { class RestAPIViewModel {
serverVersion: string = '123' orsg: Organization[] = []
refreshing: boolean = false;
async getServerVersion() { private restAPI: RestAPI = new RestAPI();
await axios({
method: "post", getAllOrgs() {
url: 'https://music.devwiki.net/rest/ping.view?v=1.16.1&c=myapp&f=json' this.restAPI.getAllOrganizations((result) => {
}).then((response: AxiosResponse) => { if (result.data) {
if (response.status == 200) { this.orsg = result.data;
let version:string = response.data['subsonic-response']['serverVersion'];
this.serverVersion = version;
Log.i(`serverVersion: ${this.serverVersion}`)
} }
}).catch((error: AxiosError) => { this.refreshing = false;
Log.e(error.message);
}) })
} }
getServerVersionByHttp() {
let request = http.createHttp();
let header: Map<string, string> = new Map();
request.request('https://qt.gtimg.cn/q=s_sh000001', {
header: {
'Content-Type': 'text/html; charset=GBK'
},
expectDataType: http.HttpDataType.ARRAY_BUFFER
}).then(res => {
let data = this.gbkToUTF8(res.result as ArrayBuffer);
Log.info(res.responseCode.toString());
})
}
gbkToUTF8(content: ArrayBuffer): string {
let textDecoderOptions: util.TextDecoderOptions = {
fatal: false,
ignoreBOM : true
}
let decodeWithStreamOptions: util.DecodeWithStreamOptions = {
stream: true
}
let textDecoder = util.TextDecoder.create('gbk', textDecoderOptions);
let retStr = textDecoder.decodeWithStream( new Uint8Array(content) , decodeWithStreamOptions);
return retStr;
}
} }

View File

@@ -26,10 +26,10 @@ class TcpSocket {
let message = String.fromCharCode(messages); let message = String.fromCharCode(messages);
messageView += message; messageView += message;
} }
Log.i(`receive message: ${messageView}`) Log.info(`receive message: ${messageView}`)
}) })
this.tcp.on('error', (error) => { this.tcp.on('error', (error) => {
Log.i(`tcp error: ${error.message}`) Log.info(`tcp error: ${error.message}`)
}) })
} }
@@ -40,19 +40,19 @@ class TcpSocket {
this.tcp.bind(address) this.tcp.bind(address)
this.tcp.connect(this.connectOptions, (error) => { this.tcp.connect(this.connectOptions, (error) => {
if (error) { if (error) {
Log.e(`connect fail: ${error.message}`); Log.error(`connect fail: ${error.message}`);
return; return;
} }
Log.i('connect success') Log.info('connect success')
}) })
} }
send(text: string) { send(text: string) {
let option: socket.TCPSendOptions = { data: text} let option: socket.TCPSendOptions = { data: text}
this.tcp.send(option).then(() => { this.tcp.send(option).then(() => {
Log.i(`send data: ${text} success`) Log.info(`send data: ${text} success`)
}).catch((error: BusinessError) => { }).catch((error: BusinessError) => {
Log.e(`send data: ${text} error: ${error.message}`) Log.error(`send data: ${text} error: ${error.message}`)
}) })
} }
} }
@@ -60,7 +60,7 @@ class TcpSocket {
@Component @Component
@Entry @Entry
export struct TcpSocketPage { struct TcpSocketPage {
tcpSocket: TcpSocket = new TcpSocket(); tcpSocket: TcpSocket = new TcpSocket();

View File

@@ -3,7 +3,7 @@ import { common, Want } from '@kit.AbilityKit';
@Component @Component
@Entry @Entry
export struct SchemePage { struct SchemePage {
build() { build() {
Column() { Column() {
TitleBar({ TitleBar({
@@ -13,16 +13,22 @@ export struct SchemePage {
} }
}) })
Button("Open").width(120).height(36).onClick(() => { Button("OpenApp").width(120).height(36).onClick(() => {
this.openScheme() this.openScheme('alipays://platformapi/startapp?appId=20000001')
}).margin({ top: 48 })
Button("OpenStore").width(120).height(36).onClick(() => {
this.openScheme('store://appgallery.huawei.com/app/detail?id=com.alipay.mobile.client')
}).margin({ top: 48 }) }).margin({ top: 48 })
} }
} }
openScheme() { openScheme(uri: string) {
let context = getContext(this) as common.UIAbilityContext; let context = getContext(this) as common.UIAbilityContext;
let wantInfo: Want = { let wantInfo: Want = {
uri: 'https://devwiki.net' // action: 'ohos.want.action.viewData',
// entities: ['entity.system.browsable'],
uri: uri
} }
context.startAbility(wantInfo); context.startAbility(wantInfo);
} }

View File

@@ -0,0 +1,48 @@
import { TitleBar } from '@devwiki/common_ui';
import { i18n } from '@kit.LocalizationKit';
import { Log } from '@devwiki/base';
const TAG = '[SetLanguagePage]'
@Entry
@Component
struct SetLanguagePage {
private readonly languageGroup = "languageGroup"
@State selectedLanguage: string = 'zh-Hans';
aboutToAppear(): void {
let languages:string[] = i18n.System.getSystemLanguages();
languages.forEach((value, index) => {
Log.info(TAG, `${index.toString()}:${value}`)
})
}
build() {
Column() {
TitleBar({
title: $r('app.string.set_language_title')
});
Row() {
Text('简体中文');
Radio({ group: this.languageGroup, value: 'zh-Hans' }).checked(this.selectedLanguage == 'zh-Hans')
.onChange(isChecked => {
if (isChecked) {
i18n.System.setAppPreferredLanguage('zh-Hans')
this.selectedLanguage = 'zh-Hans'
}
});
}
Row() {
Text('英文');
Radio({ group: this.languageGroup, value: 'en-US' }).checked(this.selectedLanguage == 'en-US')
.onChange(isChecked => {
if (isChecked) {
i18n.System.setAppPreferredLanguage('en-US')
this.selectedLanguage = 'en-US'
}
});
}
}.width('100%').height('100%')
}
}

View File

@@ -0,0 +1,42 @@
import commonEventManager from '@ohos.commonEventManager';
import Base from '@ohos.base';
@Component
@Entry
export struct SystemEventPage {
// 用于保存创建成功的订阅者对象,后续使用其完成订阅及退订的动作
subscriber: commonEventManager.CommonEventSubscriber | null = null;
// 订阅者信息
subscribeInfo: commonEventManager.CommonEventSubscribeInfo = {
events: ["usual.event.SCREEN_OFF"], // 订阅灭屏公共事件
}
aboutToAppear(): void {
// 创建订阅者回调
commonEventManager.createSubscriber(this.subscribeInfo, (err: Base.BusinessError, data: commonEventManager.CommonEventSubscriber) => {
if (err) {
console.error(`Failed to create subscriber. Code is ${err.code}, message is ${err.message}`);
return;
}
console.info('Succeeded in creating subscriber.');
this.subscriber = data;
// 订阅公共事件回调
})
// 订阅公共事件回调
if (this.subscriber !== null) {
commonEventManager.subscribe(this.subscriber, (err: Base.BusinessError, data: commonEventManager.CommonEventData) => {
if (err) {
console.error(`Failed to subscribe common event. Code is ${err.code}, message is ${err.message}`);
return;
}
})
} else {
console.error(`Need create subscriber`);
}
}
build() {
}
}

View File

@@ -1,7 +1,7 @@
@Entry({routeName: "TimerPage"}) @Entry({routeName: "TimerPage"})
@Component @Component
export struct TimerPage { struct TimerPage {
build() { build() {
} }
} }

View File

@@ -5,12 +5,12 @@ import { TitleBar } from '@devwiki/common_ui/src/main/ets/component/TitleBar';
@CustomDialog @CustomDialog
export struct WebPageDialog { export struct WebPageDialog {
@StorageLink(ScreenUtil.isPortraitKey) isPortrait: boolean = true; @StorageLink(ScreenUtil.isPortraitKey) isPortrait: boolean = true;
dialogController: CustomDialogController; dialogController?: CustomDialogController;
build() { build() {
WebPage({ WebPage({
onTitleBarLeftClick: () => { onTitleBarLeftClick: () => {
this.dialogController.close(); this.dialogController?.close();
} }
}).height(this.isPortrait ? '95%' : '90%').width(this.isPortrait ? '100%' : '50%') }).height(this.isPortrait ? '95%' : '90%').width(this.isPortrait ? '100%' : '50%')
} }
@@ -18,7 +18,7 @@ export struct WebPageDialog {
@Entry @Entry
@Component @Component
export struct WebDialogPage { struct WebDialogPage {
dialogController: CustomDialogController = new CustomDialogController({ dialogController: CustomDialogController = new CustomDialogController({
builder: WebPageDialog(), builder: WebPageDialog(),

View File

@@ -30,7 +30,6 @@ export struct WebPage {
build() { build() {
Column() { Column() {
RelativeContainer() {
TitleBar({ TitleBar({
title: this.viewModel.pageTitle, title: this.viewModel.pageTitle,
onLeftClicked: () => { onLeftClicked: () => {
@@ -44,12 +43,7 @@ export struct WebPage {
// 必须这么写 onTitleBarRightClick内部的代码才执行, // 必须这么写 onTitleBarRightClick内部的代码才执行,
// 直接 onRightClicked: this.onTitleBarRightClick 这么写, 代码不执行 // 直接 onRightClicked: this.onTitleBarRightClick 这么写, 代码不执行
onRightClicked: (event: ClickEvent) => { this.onTitleBarRightClick(event)}, onRightClicked: (event: ClickEvent) => { this.onTitleBarRightClick(event)},
}) }).width('100%')
.width('100%')
.alignRules({
top: { anchor: ComponentConst.ContainerId, align: VerticalAlign.Top },
left: { anchor: ComponentConst.ContainerId, align: HorizontalAlign.Start }
}).id("title_bar");
Divider().alignRules({ Divider().alignRules({
top: { anchor: "title_bar", align: VerticalAlign.Bottom }, top: { anchor: "title_bar", align: VerticalAlign.Bottom },
@@ -57,12 +51,7 @@ export struct WebPage {
}).width('100%').id("divider") }).width('100%').id("divider")
WebView({ param: this.viewModel.webParam, controller: this.webViewController }).width('100%') WebView({ param: this.viewModel.webParam, controller: this.webViewController }).width('100%')
.alignRules({ .layoutWeight(1).borderWidth(1).borderColor(Color.Red)
top: { anchor: "divider", align: VerticalAlign.Bottom },
left: { anchor: ComponentConst.ContainerId, align: HorizontalAlign.Start },
bottom: { anchor: ComponentConst.ContainerId, align: VerticalAlign.Bottom }
}).id("host_web")
}.width('100%').height('100%')
}.width('100%').height('100%') }.width('100%').height('100%')
} }
} }
@@ -88,7 +77,7 @@ class WebPageController extends WebViewController {
class WebPageViewModel { class WebPageViewModel {
webParam: WebViewParam = { webParam: WebViewParam = {
webUrl: "https://devwiki.net" webUrl: "https://baidu.com"
}; };
pageTitle: ResourceStr = "WebPage"; pageTitle: ResourceStr = "WebPage";

View File

@@ -0,0 +1,105 @@
import { abilityAccessCtrl, bundleManager, common, PermissionRequestResult, Permissions } from '@kit.AbilityKit';
import { BusinessError } from '@kit.BasicServicesKit';
import { geoLocationManager } from '@kit.LocationKit';
const locationPermission: Permissions[] = ['ohos.permission.LOCATION', 'ohos.permission.APPROXIMATELY_LOCATION'];
export class LocationHelper {
appInfo: bundleManager.BundleInfo;
context: common.UIAbilityContext;
atManager: abilityAccessCtrl.AtManager;
constructor(context: common.UIAbilityContext) {
this.context = context;
this.atManager = abilityAccessCtrl.createAtManager();
this.appInfo = bundleManager.getBundleInfoForSelfSync(bundleManager.BundleFlag.GET_BUNDLE_INFO_WITH_APPLICATION) // 获取应用信息
}
checkLocationPermission(callback: (isAllow: boolean) => void) {
let status = this.atManager.checkAccessTokenSync(this.appInfo.appInfo.accessTokenId, locationPermission[0])
callback(status === abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED)
}
gotoSystemSetting() {
}
// openLocation(callback:(address: string) => void) {
// let options: AMapLocationOption = {
// priority: geoLocationManager.LocationRequestPriority.FIRST_FIX, //定位优先配置选项
// scenario: geoLocationManager.LocationRequestScenario.UNSET, //定位场景设置
// timeInterval: 2, //定位时间间隔
// distanceInterval: 0, //位置报告距离间隔
// maxAccuracy: 0, //定位精度 单位:米
// allowsBackgroundLocationUpdates: false, //是否允许后台定位
// locatingWithReGeocode: true, //定位是否返回逆地理信息
// reGeocodeLanguage: AMapLocationReGeocodeLanguage.Chinese, //逆地址语言类型
// isOffset: true //是否加偏
// }
// let listener: IAMapLocationListener = {
// onLocationChanged: (location) => {
// this.getLocationAddress(location.latitude, location.longitude, 1, (err, data) => {
// if (err) {
// console.error('getAddressesFromLocation: err=' + JSON.stringify(err));
// }
// if (data) {
// console.log('getAddressesFromLocation: data=' + JSON.stringify(data));
// let loc = data[0].placeName ?? '';
// if (data[0].administrativeArea) {
// loc = loc.replace(data[0].administrativeArea, '')
// }
// if (data[0].subAdministrativeArea) {
// loc = loc.replace(data[0].subAdministrativeArea, '')
// }
// if (data[0].subLocality) {
// loc = loc.replace(data[0].subLocality, '')
// }
// if (data[0].roadName) {
// loc = loc.replace(data[0].roadName, '')
// }
// if (data[0].subRoadName) {
// loc = loc.replace(data[0].subRoadName, '')
// }
// if (data[0].subRoadName && loc === '') {
// loc = data[0].subRoadName?.toString()
// }
// callback(loc);
// }
// });
// }, onLocationError: (error) => {
// console.error(`IAMapLocationListener ${error.errorMsg}:${error.errorCode}`)
// }
// };
// this.locationManger?.setLocationListener(AMapLocationType.Updating, listener) //设置定位信息监听
// this.locationManger?.setLocationOption(AMapLocationType.Updating, options) //设置定位配置项
// this.locationManger?.startUpdatingLocation() //开启连续定位
// }
/**
* 请求定位 allowScope是否允许定位, allowPrecision: 是否允许获取精确位置
* @param callback
*/
requestPermissionsFromUser(callback: (allowScope: boolean, allowPrecision: boolean) => void): void {
this.atManager.requestPermissionsFromUser(this.context, locationPermission)
.then((data: PermissionRequestResult) => {
callback(data.authResults[1] === abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED,
data.authResults[0] === abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED);
})
.catch((err: BusinessError) => {
console.error(`Failed to request permissions from user. Code is ${err.code}, message is ${err.message}`);
})
}
getLocationAddress(latitude: number, longitude: number, maxItems: number, callback:(error: BusinessError, data: geoLocationManager.GeoAddress[]) => void) {
let reverseGeocodeRequest:geoLocationManager.ReverseGeoCodeRequest = {"latitude": latitude, "longitude": longitude, "maxItems": maxItems};
try {
geoLocationManager.getAddressesFromLocation(reverseGeocodeRequest, (err, data) => {
callback(err, data);
});
} catch (err) {
console.error("errCode:" + JSON.stringify(err));
}
}
}

View File

@@ -2,3 +2,7 @@
export class PageRouter{ export class PageRouter{
static readonly WebPage: string = "@bundle:net.devwiki.hm4demo/app/ets/pages/web/WebPage" static readonly WebPage: string = "@bundle:net.devwiki.hm4demo/app/ets/pages/web/WebPage"
} }
export enum PageName {
loadingPage = 'LoadingPage',
}

View File

@@ -0,0 +1,33 @@
import { pasteboard } from '@kit.BasicServicesKit';
class PasteboardUtil {
static async copyData(data: string, type: CopyDataType) {
try {
if (!data) {
return;
}
let mineType = pasteboard.MIMETYPE_TEXT_PLAIN;
if (type === CopyDataType.URI) {
mineType = pasteboard.MIMETYPE_TEXT_URI;
} else if (type === CopyDataType.HTML) {
mineType = pasteboard.MIMETYPE_TEXT_HTML;
}
const pasteData: pasteboard.PasteData = pasteboard.createData(mineType, data);
const systemPasteboard: pasteboard.SystemPasteboard = pasteboard.getSystemPasteboard();
await systemPasteboard.setData(pasteData);
} catch (err) {
console.error('Failed to set PasteData.');
}
}
}
export enum CopyDataType {
TEXT,
URI,
HTML
}

View File

@@ -4,11 +4,18 @@
"type": "entry", "type": "entry",
"description": "$string:module_desc", "description": "$string:module_desc",
"mainElement": "AppAbility", "mainElement": "AppAbility",
"srcEntry": "./ets/AppAbilityStage.ets",
"deviceTypes": [ "deviceTypes": [
"phone", "phone",
"tablet", "tablet",
"2in1" "2in1"
], ],
"metadata": [
{
"name": "client_id",
"value": "123456789"
}
],
"deliveryWithInstall": true, "deliveryWithInstall": true,
"installationFree": false, "installationFree": false,
"pages": "$profile:main_pages", "pages": "$profile:main_pages",
@@ -36,7 +43,18 @@
], ],
"requestPermissions": [ "requestPermissions": [
{ {
"name" : "ohos.permission.INTERNET" "name": "ohos.permission.LOCATION",
"reason": "$string:location_permission",
"usedScene": {
"when": "inuse"
}
},
{
"name": "ohos.permission.APPROXIMATELY_LOCATION",
"reason": "$string:approximately_location",
"usedScene": {
"when": "inuse"
}
} }
] ]
} }

View File

@@ -2,15 +2,27 @@
"string": [ "string": [
{ {
"name": "module_desc", "name": "module_desc",
"value": "module description" "value": "HM4Demo App"
}, },
{ {
"name": "AppAbility_desc", "name": "AppAbility_desc",
"value": "description" "value": "HM4Demo"
}, },
{ {
"name": "AppAbility_label", "name": "AppAbility_label",
"value": "label" "value": "HM4Demo"
},
{
"name": "set_language_title",
"value": "Set Language"
},
{
"name": "location_permission",
"value": "location_permission"
},
{
"name": "approximately_location",
"value": "approximately_location"
} }
] ]
} }

View File

@@ -3,10 +3,12 @@
"pages/Index", "pages/Index",
"pages/animation/CompTransitionPage", "pages/animation/CompTransitionPage",
"pages/animation/LoadingPage",
"pages/component/InputPage", "pages/component/InputPage",
"pages/component/SVGPage", "pages/component/SVGPage",
"pages/component/TextPage", "pages/component/TextPage",
"pages/component/ToastPage",
"pages/layout/LinearLayoutPage", "pages/layout/LinearLayoutPage",
"pages/layout/RelativeContainerPage", "pages/layout/RelativeContainerPage",
@@ -16,14 +18,20 @@
"pages/media/PhotoPage", "pages/media/PhotoPage",
"pages/mvvm/HomePage", "pages/mvvm/HomePage",
"pages/mvvm/ArrayBindPage",
"pages/net/TcpSocketPage", "pages/net/TcpSocketPage",
"pages/net/RestAPIPage", "pages/net/RestAPIPage",
"pages/system/SchemePage", "pages/system/SchemePage",
"pages/system/TimerPage", "pages/system/TimerPage",
"pages/system/SetLanguagePage",
"pages/web/WebPage", "pages/web/WebPage",
"pages/web/WebDialogPage" "pages/web/WebDialogPage",
"pages/map/MapPage"
] ]
} }

View File

@@ -2,15 +2,27 @@
"string": [ "string": [
{ {
"name": "module_desc", "name": "module_desc",
"value": "module description" "value": "HMDemo"
}, },
{ {
"name": "AppAbility_desc", "name": "AppAbility_desc",
"value": "description" "value": "HMDemo_Ability"
}, },
{ {
"name": "AppAbility_label", "name": "AppAbility_label",
"value": "label" "value": "HMDemo"
},
{
"name": "set_language_title",
"value": "Set Language"
},
{
"name": "location_permission",
"value": "location_permission"
},
{
"name": "approximately_location",
"value": "approximately_location"
} }
] ]
} }

View File

@@ -2,15 +2,27 @@
"string": [ "string": [
{ {
"name": "module_desc", "name": "module_desc",
"value": "模块描述" "value": "HMDemo"
}, },
{ {
"name": "AppAbility_desc", "name": "AppAbility_desc",
"value": "description" "value": "HMDemo_Ability"
}, },
{ {
"name": "AppAbility_label", "name": "AppAbility_label",
"value": "label" "value": "HMDemo"
},
{
"name": "set_language_title",
"value": "设置语言"
},
{
"name": "location_permission",
"value": "location_permission"
},
{
"name": "approximately_location",
"value": "approximately_location"
} }
] ]
} }

View File

@@ -34,12 +34,12 @@ export class BaseLocalStorage {
let options: dataPreferences.Options = { name: BaseLocalStorage.XY_DP_Name }; let options: dataPreferences.Options = { name: BaseLocalStorage.XY_DP_Name };
this.preferences = dataPreferences.getPreferencesSync(this.context, options); this.preferences = dataPreferences.getPreferencesSync(this.context, options);
} else { } else {
Log.i("LocalStorage is already init.") Log.info("LocalStorage is already init.")
} }
} }
public putData(key: string, value: dataPreferences.ValueType) { public putData(key: string, value: dataPreferences.ValueType) {
Log.i(`put sp data, key:${key}, value:${value}`) Log.info(`put sp data, key:${key}, value:${value}`)
this.preferences?.putSync(key, value); this.preferences?.putSync(key, value);
this.preferences?.flush(); this.preferences?.flush();
} }
@@ -51,7 +51,7 @@ export class BaseLocalStorage {
public getData(key: string, defaultValue: dataPreferences.ValueType): dataPreferences.ValueType | undefined { public getData(key: string, defaultValue: dataPreferences.ValueType): dataPreferences.ValueType | undefined {
let value = this.preferences?.getSync(key, defaultValue); let value = this.preferences?.getSync(key, defaultValue);
Log.i(`get sp data, key:${key}, value:${value}`) Log.info(`get sp data, key:${key}, value:${value}`)
return value; return value;
} }

View File

@@ -2,28 +2,28 @@
import hilog from '@ohos.hilog'; import hilog from '@ohos.hilog';
let domain: number = 0xFF00; let domain: number = 0xFF00;
let prefix: string = 'HM4Demo'; let prefix: string = 'HMDemo';
let format: string = `%{public}s`; let format: string = `%{public}s, %{public}s`;
export class Log { export class Log {
static d(...args: string[]) { static debug(...args: string[]) {
hilog.debug(domain, prefix, format, args); hilog.debug(domain, prefix, format, args);
} }
static i(...args: string[]) { static info(...args: string[]) {
hilog.info(domain, prefix, format, args); hilog.info(domain, prefix, format, args);
} }
static w(...args: string[]) { static warn(...args: string[]) {
hilog.warn(domain, prefix, format, args); hilog.warn(domain, prefix, format, args);
} }
static e(...args: string[]) { static error(...args: string[]) {
hilog.error(domain, prefix, format, args); hilog.error(domain, prefix, format, args);
} }
static f(...args: string[]) { static fatal(...args: string[]) {
hilog.fatal(domain,prefix, format, args); hilog.fatal(domain,prefix, format, args);
} }

View File

@@ -25,11 +25,11 @@ export class ScreenUtil {
return ScreenUtil.instance; return ScreenUtil.instance;
} }
initScreenSize(): void { initScreenSize(context: Context): void {
this.portraitListener.on('change', (result)=> { this.portraitListener.on('change', (result)=> {
AppStorage.setOrCreate(ScreenUtil.isPortraitKey, result.matches) AppStorage.setOrCreate(ScreenUtil.isPortraitKey, result.matches)
}) })
window.getLastWindow(getContext(this)) window.getLastWindow(context)
.then((windowClass: window.Window) => { .then((windowClass: window.Window) => {
let type = window.AvoidAreaType.TYPE_NAVIGATION_INDICATOR; // 以导航条避让为例 let type = window.AvoidAreaType.TYPE_NAVIGATION_INDICATOR; // 以导航条避让为例
let avoidArea = windowClass.getWindowAvoidArea(type); let avoidArea = windowClass.getWindowAvoidArea(type);
@@ -106,7 +106,7 @@ export class ScreenUtil {
} }
setWindowKeepScreenOn(isKeep: boolean) { setWindowKeepScreenOn(isKeep: boolean) {
Log.i(`setWindowKeepScreenOn:${isKeep}`) Log.info(`setWindowKeepScreenOn:${isKeep}`)
window.getLastWindow(getContext(this)) window.getLastWindow(getContext(this))
.then((windowClass: window.Window) => { .then((windowClass: window.Window) => {
windowClass.setWindowKeepScreenOn(isKeep); windowClass.setWindowKeepScreenOn(isKeep);

View File

@@ -7,13 +7,13 @@
"name": "default", "name": "default",
"type": "HarmonyOS", "type": "HarmonyOS",
"material": { "material": {
"certpath": "build_script/sign/HM4Demo.cer", "certpath": "C:\\Users\\zyz\\.ohos\\config\\default_HMDemo_i5yHT0lu8Bugf7Se0a-mWm67_DsSdIYAWNVACnIC98c=.cer",
"storePassword": "0000001B9C6223E8C618FEFD3D871B066F744A4E9C03C09D8ED7E7C7ECE6C1F53A54A6748EC341B960E492", "storePassword": "0000001B17961DDECEBACEACD9CAA1E45CB0BEF5D5A935C253F2AB99644951676ED1B6F102D2B5AD8BCBA2",
"keyAlias": "debugKey", "keyAlias": "debugKey",
"keyPassword": "0000001B63515E7120BC166D17A66B98A717DE9B06276194E4317B5317F70EA2835B8AD262B9DD4FD6AB55", "keyPassword": "0000001B72605A837A1D1827D656F3D157F771A9B6DEC8B264626F1EFBBDA8FF65464F416F4B5C7F9FA84F",
"profile": "build_script/sign/HM4Demo.p7b", "profile": "C:\\Users\\zyz\\.ohos\\config\\default_HMDemo_i5yHT0lu8Bugf7Se0a-mWm67_DsSdIYAWNVACnIC98c=.p7b",
"signAlg": "SHA256withECDSA", "signAlg": "SHA256withECDSA",
"storeFile": "build_script/sign/HM4Demo.p12" "storeFile": "C:\\Users\\zyz\\.ohos\\config\\default_HMDemo_i5yHT0lu8Bugf7Se0a-mWm67_DsSdIYAWNVACnIC98c=.p12"
} }
} }
], ],
@@ -22,8 +22,7 @@
{ {
"name": "default", "name": "default",
"signingConfig": "default", "signingConfig": "default",
"compileSdkVersion": "4.1.0(11)", "compatibleSdkVersion": "5.0.0(12)",
"compatibleSdkVersion": "4.0.0(10)",
"runtimeOS": "HarmonyOS", "runtimeOS": "HarmonyOS",
} }
], ],
@@ -81,8 +80,8 @@
] ]
}, },
{ {
"name": "native_lib", "name": "hmcalculate",
"srcPath": "./native_lib", "srcPath": "./hmcalculate",
"targets": [ "targets": [
{ {
"name": "default", "name": "default",

View File

@@ -4,3 +4,4 @@ export { WebView, WebViewController, WebViewParam } from './src/main/ets/compone
export { CommonRes, CommonMediaName } from './src/main/ets/utils/CommonRes' export { CommonRes, CommonMediaName } from './src/main/ets/utils/CommonRes'
export { PhoneInput } from './src/main/ets/component/InputComponent' export { PhoneInput } from './src/main/ets/component/InputComponent'
export { Toast } from './src/main/ets/utils/Toast'

View File

@@ -8,7 +8,6 @@ function textInputStyle() {
.padding(5) .padding(5)
} }
@Preview
@Component @Component
export struct PhoneInput { export struct PhoneInput {
@Prop countryCode: string = "+86" @Prop countryCode: string = "+86"
@@ -26,7 +25,7 @@ export struct PhoneInput {
Row() { Row() {
Text(this.countryCode) Text(this.countryCode)
.height(44) .height(44)
Image($r('app.media.ic_chevron_down')) Image($r(`app.media.ic_chevron_down`))
.objectFit(ImageFit.Contain) .objectFit(ImageFit.Contain)
.width(12) .width(12)
.height(12) .height(12)
@@ -55,7 +54,7 @@ export struct PhoneInput {
}) })
.width('100%') .width('100%')
Image($r('app.media.ic_clear_circle')) Image($r(`app.media.ic_clear_circle`))
.width(18) .width(18)
.height(18) .height(18)
.backgroundColor(Color.Green) .backgroundColor(Color.Green)

View File

@@ -15,21 +15,20 @@ export enum TitleBarMenuType{
Text = 2 Text = 2
} }
@Preview
@Component @Component
export struct TitleBar { export struct TitleBar {
@Prop title: ResourceStr; @Prop title: ResourceStr = '';
@Prop barHeight: number = 48; @Prop barHeight: number = 48;
@Prop menuPadding: number = 8; @Prop menuPadding: number = 8;
@Prop leftText: ResourceStr = ""; @Prop leftText: ResourceStr = "";
@Prop leftIcon: Resource = $r("app.media.ic_chevron_left"); @Prop leftIcon: Resource = $r(`app.media.ic_chevron_left`);
@Prop leftMenuType: TitleBarMenuType = TitleBarMenuType.Icon; @Prop leftMenuType: TitleBarMenuType = TitleBarMenuType.Icon;
@Prop rightText: ResourceStr = ""; @Prop rightText: ResourceStr = "";
@Prop rightIcon: Resource = $r("app.media.ic_close"); @Prop rightIcon: Resource = $r(`app.media.ic_close`);
@Prop rightMenuType: TitleBarMenuType = TitleBarMenuType.None; @Prop rightMenuType: TitleBarMenuType = TitleBarMenuType.None;
@Prop titleTextAlign: TextAlign = TextAlign.Start; @Prop titleTextAlign: TextAlign = TextAlign.Start;

View File

@@ -1,5 +1,7 @@
import web_webview from '@ohos.web.webview'; import web_webview from '@ohos.web.webview';
import { WebScriptCallback, WebScriptFunction } from './WebScript'; import { WebScriptCallback, WebScriptFunction } from './WebScript';
import { picker } from '@kit.CoreFileKit';
import { BusinessError } from '@kit.BasicServicesKit';
export class WebViewParam { export class WebViewParam {
webUrl: string = ""; webUrl: string = "";
@@ -9,6 +11,8 @@ export class WebViewParam {
export struct WebView { export struct WebView {
private webviewController: web_webview.WebviewController = new web_webview.WebviewController(); private webviewController: web_webview.WebviewController = new web_webview.WebviewController();
selectOptions?: picker.PhotoSelectOptions | picker.DocumentSelectOptions;
viewPicker?: picker.PhotoViewPicker | picker.DocumentViewPicker;
controller: WebViewController = new WebViewController(); controller: WebViewController = new WebViewController();
@Prop @Watch("onParamChanged")param: WebViewParam = new WebViewParam(); @Prop @Watch("onParamChanged")param: WebViewParam = new WebViewParam();
@@ -33,6 +37,21 @@ export struct WebView {
controller: this.webviewController controller: this.webviewController
}) })
.onPageEnd(() => { this.controller.onPageEnd(this.webviewController.getTitle()) }) .onPageEnd(() => { this.controller.onPageEnd(this.webviewController.getTitle()) })
.onShowFileSelector( (event) =>{
let uri: string[] | null = null;
this.selectOptions = new picker.DocumentSelectOptions();
this.viewPicker = new picker.DocumentViewPicker();
this.viewPicker.select(this.selectOptions).then((result) => {
uri = result;
console.info('DocumentViewPicker.select to file succeed and uri is:' + uri);
if (event) {
event.result.handleFileList(uri);
}
}).catch((err: BusinessError) => {
console.error(`Invoke documentViewPicker.select failed, code is ${err.code}, message is ${err.message}`);
})
return true;
})
.width('100%') .width('100%')
.height('100%'); .height('100%');
} }

View File

@@ -7,27 +7,27 @@ export class CommonRes {
} }
public static getIconRefresh(): Resource { public static getIconRefresh(): Resource {
return $r("app.media.ic_refresh"); return $r(`app.media.ic_refresh`);
} }
public static getIconChevronLeft(): Resource { public static getIconChevronLeft(): Resource {
return $r("app.media.ic_chevron_left"); return $r(`app.media.ic_chevron_left`);
} }
public static getIconChevronRight(): Resource { public static getIconChevronRight(): Resource {
return $r("app.media.ic_chevron_right"); return $r(`app.media.ic_chevron_right`);
} }
public static getIconClose(): Resource { public static getIconClose(): Resource {
return $r("app.media.ic_close"); return $r(`app.media.ic_close`);
} }
public static getIconEyeOn(): Resource { public static getIconEyeOn(): Resource {
return $r("app.media.ic_eye_on"); return $r(`app.media.ic_eye_on`);
} }
public static getIconEyeOff(): Resource { public static getIconEyeOff(): Resource {
return $r("app.media.ic_eye_off"); return $r(`app.media.ic_eye_off`);
} }
public static getImage(resName: string): Resource { public static getImage(resName: string): Resource {

View File

@@ -0,0 +1,26 @@
import { util } from '@kit.ArkTS';
export class Res {
static getRawFileContent(name: string): string {
let content = getContext().resourceManager.getRawFileContentSync(name);
let textDecoderOptions: util.TextDecoderOptions = {
fatal: false,
ignoreBOM : true
}
let decodeWithStreamOptions: util.DecodeWithStreamOptions = {
stream: true
}
let textDecoder = util.TextDecoder.create('utf-8', textDecoderOptions);
let retStr = textDecoder.decodeWithStream( content , decodeWithStreamOptions);
return retStr;
}
static getResStr(descName: string, ...rest: string[]): ResourceStr {
try {
return $r(`app.string.${descName}`, ...rest);
} catch (e) {
return '';
}
}
}

View File

@@ -1,11 +1,12 @@
import promptAction from '@ohos.promptAction'; import promptAction from '@ohos.promptAction';
export class Toast { export class Toast {
static showToast(message: ResourceStr) { static showToast(message: ResourceStr, topmost: boolean = false) {
promptAction.showToast({ promptAction.showToast({
message: message, message: message,
duration: 2000, duration: 2000,
bottom: "50%" bottom: "50%",
showMode: promptAction.ToastShowMode.TOP_MOST
}); });
} }
} }

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><title>loading</title><path d="M12,4V2A10,10 0 0,0 2,12H4A8,8 0 0,1 12,4Z" /></svg>

After

Width:  |  Height:  |  Size: 143 B

View File

@@ -1,11 +1,28 @@
@echo off @echo off
chcp 65001 > nul chcp 65001 > nul
set native_path=D:\AppData\Huawei\Sdk\HarmonyOS-NEXT-DP2\base\native\
set toolchain=%native_path%build\cmake\ohos.toolchain.cmake set "native_path=C:\Program Files\Huawei\DevEco Studio5\sdk\HarmonyOS-NEXT-DB1\openharmony\native\"
set cmake_root=%native_path%build-tools\cmake\ :: IF NOT "%~2" == "" (
set cmake_path=%cmake_root%bin\cmake.exe :: set "native_path=%~2"
set ninja_path=%cmake_root%bin\ninja.exe :: )
set make_path=C:\MinGW\msys\1.0\bin\make.exe echo native_path: "%native_path%"
set "toolchain=%native_path%build\cmake\ohos.toolchain.cmake"
echo toolchain: "%toolchain%"
set "cmake_root=%native_path%build-tools\cmake\"
echo cmake_root: "%cmake_root%"
set "cmake_path=%cmake_root%bin\cmake.exe"
echo cmake_path: "%cmake_path%"
set "ninja_path=%cmake_root%bin\ninja.exe"
echo ninja_path: "%ninja_path%"
set "make_path=C:\MinGW\msys\1.0\bin\make.exe"
echo make_path: %make_path%
set "arch=arm64-v8a"
IF NOT "%~1" == "" (
set "arch=%~1"
)
echo arch: "%arch%"
if exist build ( if exist build (
del /q /s build del /q /s build
@@ -14,16 +31,19 @@ if exist build (
) )
if exist dist ( if exist dist (
del /q /s dist cd dist
if exist "%arch%" (
del /q /s ""%arch%"
)
cd ../
) )
cd build cd build
:: 使用 make 构建 :: 使用 make 构建
:: %cmake_path% -G"Unix Makefiles" -DCMAKE_MAKE_PROGRAM="%make_path%" -DOHOS_STL=c++_static -DOHOS_ARCH=arm64-v8a -DOHOS_PLATFORM=OHOS -DCMAKE_TOOLCHAIN_FILE=%toolchain% .. :: "%cmake_path%" -G "Unix Makefiles" -DCMAKE_MAKE_PROGRAM="%make_path%" -DOHOS_STL=c++_static -DOHOS_ARCH="%arch%" -DOHOS_PLATFORM=OHOS -DCMAKE_TOOLCHAIN_FILE="%toolchain%" ..
:: %make_path% :: %make_path%
:: 使用 ninja 构建 :: 使用 ninja 构建
%cmake_path% -GNinja -DCMAKE_MAKE_PROGRAM="%ninja_path%" -DOHOS_STL=c++_static -DOHOS_ARCH=arm64-v8a -DOHOS_PLATFORM=OHOS -DCMAKE_TOOLCHAIN_FILE=%toolchain% .. "%cmake_path%" -G "Ninja" -D CMAKE_MAKE_PROGRAM="%ninja_path%" -D OHOS_STL=c++_static -D OHOS_ARCH="%arch%" -D OHOS_PLATFORM=OHOS -D CMAKE_TOOLCHAIN_FILE="%toolchain%" ..
%ninja_path% "%ninja_path%"
cd ../ cd ../

1
cppLib/build_x86.bat Normal file
View File

@@ -0,0 +1 @@
build.bat "x86_64"

Binary file not shown.

BIN
cppLib/dist/lib/x86_64/libcalculate.so vendored Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

2
hmcalculate/Index.ets Normal file
View File

@@ -0,0 +1,2 @@
export { Calculator } from './src/main/ets/Calculator'
export { CalculateInfo } from './src/main/ets/CalculateInfo'

View File

@@ -4,7 +4,11 @@
"externalNativeOptions": { "externalNativeOptions": {
"path": "./src/main/cpp/CMakeLists.txt", "path": "./src/main/cpp/CMakeLists.txt",
"arguments": "", "arguments": "",
"cppFlags": "" "cppFlags": "",
"abiFilters": [
"arm64-v8a",
"x86_64"
]
} }
}, },
"buildOptionSet": [ "buildOptionSet": [

View File

@@ -1,5 +1,5 @@
{ {
"name": "@devwiki/native_lib", "name": "@devwiki/hmcalculate",
"version": "1.0.0", "version": "1.0.0",
"description": "Please describe the basic information.", "description": "Please describe the basic information.",
"main": "Index.ets", "main": "Index.ets",
@@ -7,6 +7,6 @@
"license": "Apache-2.0", "license": "Apache-2.0",
"packageType": "InterfaceHar", "packageType": "InterfaceHar",
"dependencies": { "dependencies": {
"native_lib.so": "file:./src/main/cpp/types/libnatvie_lib" "libhmcalculate.so": "file:./src/main/cpp/types/libhmcalculate"
} }
} }

View File

@@ -0,0 +1,74 @@
# the minimum version of CMake.
cmake_minimum_required(VERSION 3.4.1)
project(hmcalculate)
set(NATIVERENDER_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR})
add_definitions(-DOHOS_PLATFORM)
if(DEFINED PACKAGE_FIND_FILE)
include(${PACKAGE_FIND_FILE})
endif()
include_directories(${NATIVERENDER_ROOT_PATH}
${NATIVERENDER_ROOT_PATH}/include)
add_library(hmcalculate SHARED
napi_init.cpp
CalculateAdaptor.cpp)
find_library(
# Sets the name of the path variable.
EGL-lib
# Specifies the name of the NDK library that
# you want CMake to locate.
EGL
)
find_library(
# Sets the name of the path variable.
GLES-lib
# Specifies the name of the NDK library that
# you want CMake to locate.
GLESv3
)
find_library(
# Sets the name of the path variable.
hilog-lib
# Specifies the name of the NDK library that
# you want CMake to locate.
hilog_ndk.z
)
find_library(
# Sets the name of the path variable.
libnapi-lib
# Specifies the name of the NDK library that
# you want CMake to locate.
ace_napi.z
)
find_library(
# Sets the name of the path variable.
libace-lib
# Specifies the name of the NDK library that
# you want CMake to locate.
ace_ndk.z
)
find_library(
# Sets the name of the path variable.
libuv-lib
# Specifies the name of the NDK library that
# you want CMake to locate.
uv
)
target_link_libraries(hmcalculate PUBLIC
${EGL-lib}
${GLES-lib}
${hilog-lib}
${libnapi-lib}
${libace-lib}
${libuv-lib}
${NATIVERENDER_ROOT_PATH}/../../../../cppLib/dist/lib/${OHOS_ARCH}/libcalculate.so)

View File

@@ -1,7 +1,6 @@
#ifndef CPPLIB_LIBRARY_H #ifndef CPPLIB_LIBRARY_H
#define CPPLIB_LIBRARY_H #define CPPLIB_LIBRARY_H
#include <string>
#include "CalculateInfo.h" #include "CalculateInfo.h"
class Calculate { class Calculate {

View File

@@ -0,0 +1,115 @@
//
// Created on 2024/4/22.
//
// Node APIs are not fully supported. To solve the compilation error of the interface cannot be found,
// please include "napi/native_api.h".
#include "CalculateAdaptor.h"
#include "js_native_api.h"
#include "Calculate.h"
#include <string>
#include <stdint.h>
CalculateAdaptor::CalculateAdaptor() {
_calculate = &Calculate::getInstance();
}
CalculateAdaptor::CalculateAdaptor(napi_env env, napi_value thisVar) {
_calculate = &Calculate::getInstance();
}
CalculateAdaptor::~CalculateAdaptor() {
}
CalculateAdaptor *util_get_napi_info(napi_env env, napi_callback_info cbinfo, size_t argc, napi_value *argv)
{
napi_value thisVar = nullptr;
void *data = nullptr;
napi_get_cb_info(env, cbinfo, &argc, argv, &thisVar, &data);
CalculateAdaptor *calculator = nullptr;
napi_unwrap(env, thisVar, (void **)&calculator);
return calculator;
}
napi_value calculate_add(napi_env env, napi_callback_info info) {
size_t argc = 2;
napi_value argv[2] = {0};
CalculateAdaptor *calculator = util_get_napi_info(env, info, argc, argv);
int32_t result = 0;
napi_status a = napi_ok;
a = napi_get_value_int32(env, argv[0], &result);
napi_status b = napi_ok;
b = napi_get_value_int32(env, argv[1], &result);
napi_value value;
napi_create_int32(env, calculator->_calculate->add(a, b), &value);
return value;
}
napi_value calculate_getInfo(napi_env env, napi_callback_info info) {
size_t argc = 0;
napi_value argv[1] = {0};
CalculateAdaptor *calculator = util_get_napi_info(env, info, argc, argv);
CalculateInfo info2;
info2.name = calculator->_calculate->getInfo().name;
info2.versionCode = calculator->_calculate->getInfo().versionCode;
info2.versionName = calculator->_calculate->getInfo().versionName;
napi_value js_frame;
napi_create_object(env, &js_frame);
util_set_object_string_property_value(env, js_frame, "name", info2.name.c_str());
util_set_object_string_property_value(env, js_frame, "versionName", info2.versionName.c_str());
util_set_object_int32_property_value(env, js_frame, "versionCode", info2.versionCode);
return js_frame;
}
napi_value util_create_int32_value(napi_env env, int32_t arg)
{
napi_value value;
napi_status status = napi_create_int32(env, arg, &value);
return value;
}
napi_status util_set_object_int32_property_value(napi_env env, napi_value object, const char *name, int32_t value)
{
napi_value js_value = util_create_int32_value(env, value);
return napi_set_named_property(env, object, name, js_value);
}
napi_value util_create_string_value(napi_env env, const char *arg)
{
napi_value value;
napi_status status = napi_create_string_utf8(env, arg, NAPI_AUTO_LENGTH, &value);
return value;
}
napi_status util_set_object_string_property_value(napi_env env, napi_value object, const char *name, const char *value)
{
napi_value js_value = util_create_string_value(env, value);
return napi_set_named_property(env, object, name, js_value);
}
char *util_get_object_string_property_value(napi_env env, napi_value arg, const char *name)
{
napi_status status = napi_ok;
napi_value js_result;
status = napi_get_named_property(env, arg, name, &js_result);
if (napi_ok == status) {
return util_get_string_value(env, js_result);
}
return "";
}
char *util_get_string_value(napi_env env, napi_value arg)
{
size_t len = 0;
napi_get_value_string_utf8(env, arg, nullptr, 0, &len); // 获取字符串长度到len
char *buf = new char[len + 1]; // 分配合适大小的char数组
napi_get_value_string_utf8(env, arg, buf, len + 1, &len); // 获取字符串
return buf;
}

View File

@@ -7,16 +7,16 @@
#ifndef HM4DEMO_CALCULATOR_H #ifndef HM4DEMO_CALCULATOR_H
#define HM4DEMO_CALCULATOR_H #define HM4DEMO_CALCULATOR_H
#include "CalculateInfo.h"
#include "Calculate.h" #include "Calculate.h"
#include "js_native_api.h" #include "js_native_api.h"
#include <stdint.h>
class CalculateAdaptor { class CalculateAdaptor {
public: public:
CalculateAdaptor(); CalculateAdaptor();
CalculateAdaptor(napi_env env, napi_value thisVar); CalculateAdaptor(napi_env env, napi_value thisVar);
~CalculateAdaptor(); virtual ~CalculateAdaptor();
Calculate *_calculate; Calculate *_calculate = nullptr;
}; };
CalculateAdaptor *util_get_napi_info(napi_env env, napi_callback_info cbinfo, size_t argc, napi_value *argv); CalculateAdaptor *util_get_napi_info(napi_env env, napi_callback_info cbinfo, size_t argc, napi_value *argv);
@@ -24,5 +24,12 @@ CalculateAdaptor *util_get_napi_info(napi_env env, napi_callback_info cbinfo, si
napi_value calculate_add(napi_env env, napi_callback_info info); napi_value calculate_add(napi_env env, napi_callback_info info);
napi_value calculate_getInfo(napi_env env, napi_callback_info info); napi_value calculate_getInfo(napi_env env, napi_callback_info info);
napi_value util_create_int32_value(napi_env env, int32_t arg);
napi_status util_set_object_int32_property_value(napi_env env, napi_value object, const char *name, int32_t value);
napi_value util_create_string_value(napi_env env, const char *arg);
napi_status util_set_object_string_property_value(napi_env env, napi_value object, const char *name, const char *value);
char *util_get_object_string_property_value(napi_env env, napi_value arg, const char *name);
char *util_get_string_value(napi_env env, napi_value arg);
#endif //HM4DEMO_CALCULATOR_H #endif //HM4DEMO_CALCULATOR_H

View File

@@ -1,6 +1,6 @@
#include "napi/native_api.h" #include "napi/native_api.h"
#include "CalculateAdaptor.h"
#include "js_native_api.h" #include "js_native_api.h"
#include "CalculateAdaptor.h"
napi_value JS_Constructor(napi_env env, napi_callback_info info) { napi_value JS_Constructor(napi_env env, napi_callback_info info) {
napi_value thisVar = nullptr; napi_value thisVar = nullptr;
@@ -18,9 +18,6 @@ napi_value JS_Constructor(napi_env env, napi_callback_info info) {
return thisVar; return thisVar;
} }
EXTERN_C_START
napi_value Init(napi_env env, napi_value exports) napi_value Init(napi_env env, napi_value exports)
{ {
const char className[] = "CalculateAdaptor"; const char className[] = "CalculateAdaptor";
@@ -35,19 +32,18 @@ napi_value Init(napi_env env, napi_value exports)
napi_set_named_property(env, exports, "CalculateAdaptor", result); napi_set_named_property(env, exports, "CalculateAdaptor", result);
return exports; return exports;
} }
EXTERN_C_END
static napi_module demoModule = { static napi_module demoModule = {
.nm_version = 1, .nm_version = 1,
.nm_flags = 0, .nm_flags = 0,
.nm_filename = nullptr, .nm_filename = nullptr,
.nm_register_func = Init, .nm_register_func = Init,
.nm_modname = "native_lib", .nm_modname = "hmcalculate",
.nm_priv = ((void*)0), .nm_priv = ((void*)0),
.reserved = { 0 }, .reserved = { 0 },
}; };
extern "C" __attribute__((constructor)) void RegisterNatvie_libModule(void) extern "C" __attribute__((constructor)) void RegisterHmcalculateModule(void)
{ {
napi_module_register(&demoModule); napi_module_register(&demoModule);
} }

View File

@@ -1,4 +1,4 @@
export class CalculateAdapter { export class CalculateAdaptor {
add(a: number, b: number): number; add(a: number, b: number): number;
getInfo(): Object; getInfo(): Object;
} }

View File

@@ -1,6 +1,6 @@
{ {
"name": "native_lib.so", "name": "libhmcalculate.so",
"types": "./index.d.ts", "types": "./index.d.ts",
"version": "", "version": "1.0.0",
"description": "Please describe the basic information." "description": "Please describe the basic information."
} }

View File

@@ -1,12 +1,12 @@
import { CalculateAdapter } from 'native_lib.so' import { CalculateAdaptor } from 'libhmcalculate.so'
import { CalculateInfo } from './CalculateInfo' import { CalculateInfo } from './CalculateInfo'
export class Calculator { export class Calculator {
private adaptor!:CalculateAdapter; private adaptor!:CalculateAdaptor;
constructor() { constructor() {
this.adaptor = new CalculateAdapter(); this.adaptor = new CalculateAdaptor();
} }
add(a:number, b: number): number { add(a:number, b: number): number {

View File

@@ -1,6 +1,6 @@
{ {
"module": { "module": {
"name": "native_lib", "name": "hmcalculate",
"type": "shared", "type": "shared",
"description": "$string:shared_desc", "description": "$string:shared_desc",
"deviceTypes": [ "deviceTypes": [

View File

@@ -1,7 +1,6 @@
{ {
"hvigorVersion": "file:../dependencies/hvigor-4.1.1.tgz", "modelVersion": "5.0.0",
"dependencies": { "dependencies": {
"@ohos/hvigor-ohos-plugin": "file:../dependencies/hvigor-ohos-plugin-4.1.1.tgz",
}, },
"execution": { "execution": {
// "analyze": "default", /* Define the build analyze mode. Value: [ "default" | "verbose" | false ]. Default: "default" */ // "analyze": "default", /* Define the build analyze mode. Value: [ "default" | "verbose" | false ]. Default: "default" */

File diff suppressed because one or more lines are too long

54
hvigorw
View File

@@ -1,54 +0,0 @@
#!/bin/bash
# ----------------------------------------------------------------------------
# Hvigor startup script, version 1.0.0
#
# Required ENV vars:
# ------------------
# NODE_HOME - location of a Node home dir
# or
# Add /usr/local/nodejs/bin to the PATH environment variable
# ----------------------------------------------------------------------------
HVIGOR_APP_HOME="`pwd -P`"
HVIGOR_WRAPPER_SCRIPT=${HVIGOR_APP_HOME}/hvigor/hvigor-wrapper.js
#NODE_OPTS="--max-old-space-size=4096"
fail() {
echo "$*"
exit 1
}
set_executable_node() {
EXECUTABLE_NODE="${NODE_HOME}/bin/node"
if [ -x "$EXECUTABLE_NODE" ]; then
return
fi
EXECUTABLE_NODE="${NODE_HOME}/node"
if [ -x "$EXECUTABLE_NODE" ]; then
return
fi
fail "ERROR: NODE_HOME is set to an invalid directory,check $NODE_HOME\n\nPlease set NODE_HOME in your environment to the location where your nodejs installed"
}
# Determine node to start hvigor wrapper script
if [ -n "${NODE_HOME}" ]; then
set_executable_node
else
EXECUTABLE_NODE="node"
command -v ${EXECUTABLE_NODE} &> /dev/null || fail "ERROR: NODE_HOME not set and 'node' command not found"
fi
# Check hvigor wrapper script
if [ ! -r "$HVIGOR_WRAPPER_SCRIPT" ]; then
fail "ERROR: Couldn't find hvigor/hvigor-wrapper.js in ${HVIGOR_APP_HOME}"
fi
if [ -z "${NODE_OPTS}" ]; then
NODE_OPTS="--"
fi
# start hvigor-wrapper script
exec "${EXECUTABLE_NODE}" "${NODE_OPTS}" \
"${HVIGOR_WRAPPER_SCRIPT}" "$@"

View File

@@ -1,54 +0,0 @@
@rem
@rem ----------------------------------------------------------------------------
@rem Hvigor startup script for Windows, version 1.0.0
@rem
@rem Required ENV vars:
@rem ------------------
@rem NODE_HOME - location of a Node home dir
@rem or
@rem Add %NODE_HOME%/bin to the PATH environment variable
@rem ----------------------------------------------------------------------------
@rem
@echo off
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
set WRAPPER_MODULE_PATH=%APP_HOME%\hvigor\hvigor-wrapper.js
set NODE_EXE=node.exe
@rem set NODE_OPTS="--max-old-space-size=4096"
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
if not defined NODE_OPTS set NODE_OPTS="--"
@rem Find node.exe
if defined NODE_HOME (
set NODE_HOME=%NODE_HOME:"=%
set NODE_EXE_PATH=%NODE_HOME%/%NODE_EXE%
)
%NODE_EXE% --version >NUL 2>&1
if "%ERRORLEVEL%" == "0" (
"%NODE_EXE%" "%NODE_OPTS%" "%WRAPPER_MODULE_PATH%" %*
) else if exist "%NODE_EXE_PATH%" (
"%NODE_EXE%" "%NODE_OPTS%" "%WRAPPER_MODULE_PATH%" %*
) else (
echo.
echo ERROR: NODE_HOME is not set and no 'node' command could be found in your PATH.
echo.
echo Please set the NODE_HOME variable in your environment to match the
echo location of your NodeJs installation.
)
if "%ERRORLEVEL%" == "0" (
if "%OS%" == "Windows_NT" endlocal
) else (
exit /b %ERRORLEVEL%
)

View File

@@ -1 +0,0 @@
export { CalculateAdapter } from './src/main/cpp/types/libnatvie_lib/index'

View File

@@ -1,19 +0,0 @@
# the minimum version of CMake.
cmake_minimum_required(VERSION 3.4.1)
project(myNpmLib)
set(NATIVERENDER_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR})
if(DEFINED PACKAGE_FIND_FILE)
include(${PACKAGE_FIND_FILE})
endif()
include_directories(${NATIVERENDER_ROOT_PATH}
${NATIVERENDER_ROOT_PATH}/include)
add_library(native_lib SHARED
napi_init.cpp
CalculateInfo.h
CalculateAdaptor.cpp)
target_link_libraries(native_lib PUBLIC ../../../../cppLib/dist/lib/arm64-v8a/libcalculate.so)

View File

@@ -1,64 +0,0 @@
//
// Created on 2024/4/22.
//
// Node APIs are not fully supported. To solve the compilation error of the interface cannot be found,
// please include "napi/native_api.h".
#include "CalculateAdaptor.h"
#include "Calculate.h"
#include "CalculateInfo.h"
CalculateAdaptor::CalculateAdaptor() {
_calculate = &Calculate::getInstance();
}
CalculateAdaptor::CalculateAdaptor(napi_env env, napi_value thisVar) {
_calculate = &Calculate::getInstance();
}
CalculateAdaptor::~CalculateAdaptor() {
}
CalculateAdaptor *util_get_napi_info(napi_env env, napi_callback_info cbinfo, size_t argc, napi_value *argv)
{
napi_value thisVar = nullptr;
void *data = nullptr;
napi_get_cb_info(env, cbinfo, &argc, argv, &thisVar, &data);
CalculateAdaptor *calculator = nullptr;
napi_unwrap(env, thisVar, (void **)&calculator);
return calculator;
}
napi_value calculate_add(napi_env env, napi_callback_info info) {
size_t argc = 2;
napi_value argv[2] = {0};
CalculateAdaptor *calculator = util_get_napi_info(env, info, argc, argv);
int32_t result = 0;
napi_status a = napi_ok;
a = napi_get_value_int32(env, argv[0], &result);
napi_status b = napi_ok;
b = napi_get_value_int32(env, argv[1], &result);
napi_value value;
napi_create_int32(env, calculator->_calculate->add(a, b), &value);
return value;
}
napi_value calculate_getInfo(napi_env env, napi_callback_info info) {
size_t argc = 0;
napi_value argv[1] = {0};
CalculateAdaptor *calculator = util_get_napi_info(env, info, argc, argv);
CalculateInfo info2;
info2.name = calculator->_calculate->getInfo().name;
info2.versionCode = calculator->_calculate->getInfo().versionCode;
info2.versionName = calculator->_calculate->getInfo().versionName;
napi_value value;
return value;
}

View File

@@ -1,5 +0,0 @@
import localUnitTest from './LocalUnit.test';
export default function testsuite() {
localUnitTest();
}

View File

@@ -1,33 +0,0 @@
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);
});
});
}

View File

@@ -1,4 +1,5 @@
{ {
"modelVersion": "5.0.0",
//项目名称 //项目名称
"name": "hm4demo", "name": "hm4demo",
//项目版本号 //项目版本号

View File

@@ -1,19 +1,29 @@
本项目代码地址为: [Harmony/HM4Demo - HM4Demo - DevWiki Gitea](https://git.devwiki.net/Harmony/HM4Demo) 本项目代码地址为: [Harmony/HMDemo - HMDemo - DevWiki Gitea](https://git.devwiki.net/Harmony/HMDemo)
提交时会同步更新至: 提交时会同步更新至:
- github: [Dev-Wiki/HM4Demo](https://github.com/Dev-Wiki/HM4Demo) - github: [Dev-Wiki/HMDemo](https://github.com/Dev-Wiki/HMDemo)
- gitee : [DevWiki/HM4Demo](https://gitee.com/devwiki/HM4Demo) - gitee : [DevWiki/HMDemo](https://gitee.com/devwiki/HMDemo)
[TOC]
# 项目概要 # 项目概要
## 重要说明 ## 1. 重要说明
本项目为 HM4项目,其中: 目前分支如下:
### 1.1 master分支
基于API11,即 DevEco使用 4.x或者 5.0.3.200版本
- compileSdkVersion : 4.1.0(11) - compileSdkVersion : 4.1.0(11)
- compatibleSdkVersion: 4.0.0(10) - compatibleSdkVersion: 4.0.0(10)
### 1.2 api12分支
基于API12, DevEco使用 5.0.3.300之后版本
请使用API对应的DevEco进行编译. 请使用API对应的DevEco进行编译.
### 1.3项目模块
本项目模块分为: 本项目模块分为:
- app: 主入口模块 - app: 主入口模块
- common_ui : 通用UI动态共享库模块 - common_ui : 通用UI动态共享库模块
@@ -22,19 +32,21 @@
- native_lib: 包含C++ 的 shared 模块 - native_lib: 包含C++ 的 shared 模块
## app模块 ## 2. app模块
- [MVVM架构](app/src/main/ets/pages/mvvm/HomePage.ets) - [动画](app/src/main/ets/pages/animation)
- [组件](app/src/main/ets/pages/component)
- [web功能](app/src/main/ets/pages/web)
- [布局学习](app/src/main/ets/pages/layout) - [布局学习](app/src/main/ets/pages/layout)
- [线性布局](app/src/main/ets/pages/layout/LinearLayoutPage.ets) - [线性布局](app/src/main/ets/pages/layout/LinearLayoutPage.ets)
- [动画](app/src/main/ets/pages/animation)
- [多媒体](app/src/main/ets/pages/media) - [多媒体](app/src/main/ets/pages/media)
- [AVPlayer](app/src/main/ets/pages/media/AVPlayerPage.ets) - [AVPlayer](app/src/main/ets/pages/media/AVPlayerPage.ets)
- [照片选择](app/src/main/ets/pages/media/PhotoPage.ets) - [照片选择](app/src/main/ets/pages/media/PhotoPage.ets)
- [MVVM架构](app/src/main/ets/pages/mvvm/HomePage.ets)
- [网络](app/src/main/ets/pages/net)
- [系统功能](app/src/main/ets/pages/system)
- [web功能](app/src/main/ets/pages/web)
## common ui模块 ## 3. common ui模块
包含的组件有: 包含的组件有:
@@ -44,7 +56,7 @@
## base 模块 ## 4. base 模块
事件相关: 事件相关:
- 事件发射器: [Emitter](base/src/main/ets/event/Emitter.ets) - 事件发射器: [Emitter](base/src/main/ets/event/Emitter.ets)