Advertisement · 728 × 90
#
Hashtag
#harmonyosnext
Advertisement · 728 × 90
Preview
BMW iX3 Long Wheelbase confirmed for Malaysia ahead of Beijing Auto Show 2026 debut - SoyaCincau The BMW iX3 Long Wheelbase will be released in China as well as Malaysia, Indonesia, Thailand and India. It boasts over 900km of CLTC-rated range and 400kW DC charging.

BMW iX3 Long Wheelbase confirmed for Malaysia ahead of Beijing Auto Show 2026 debut #beijingautoshow2026 #bmw #bmwix3 #bmwix3l #bmwix3longwheelbase #bmwix3lwb #chinaautoshow2026 #deepseek #ev #harmonyosnext #huawei #news

0 0 0 0
La Separación Total: Huawei Lanza HarmonyOS NEXT para Todos sus Dispositivos de 2025, Buscando la Soberanía Tecnológica.

La Separación Total: Huawei Lanza HarmonyOS NEXT para Todos sus Dispositivos de 2025, Buscando la Soberanía Tecnológica.

Huawei: Dispositivos 2025 usarán HarmonyOS NEXT. SO con kernel propio (sin AOSP/Linux). Meta: independencia tech. Despliegue inicial solo en China. #Huawei #HarmonyOSNEXT #China

0 0 0 0
Preview
Introduction to HarmonyOS Next Logging Tools Introduction to HarmonyOS Next Logging Tools In HarmonyOS Next development, logs are the...

Introduction to HarmonyOS Next Logging Tools Introduction to HarmonyOS Next Logging Tools In HarmonyOS Next development, logs are the primary means for debugging and problem-solving. Whether using ...

#harmonyosnext

Origin | Interest | Match

0 0 0 0
Preview
Like Animation Implementation, Grid Visible Items, Refresh Component, Code Specifications, State Variables [Daily HarmonyOS Next Knowledge] Like Animation Implementation, Grid Visible Items, Refresh...

Like Animation Implementation, Grid Visible Items, Refresh Component, Code Specifications, State Variables [Daily HarmonyOS Next Knowledge] Like Animation Implementation, Grid Visible Items, Refres...

#harmonyosnext

Origin | Interest | Match

0 0 0 0
Preview
Best Practices for PushKit in Assisting IM Message Notification Scenarios HarmonyOS Next IM Combat: Best Practices for PushKit in Assisting IM Message Notification...

Best Practices for PushKit in Assisting IM Message Notification Scenarios HarmonyOS Next IM Combat: Best Practices for PushKit in Assisting IM Message Notification Scenarios Background Introduction...

#harmonyosnext

Origin | Interest | Match

0 0 0 0
Preview
Mutual invocation between application side and front-end pages (C/C++) Native JSBridge Implementation in HarmonyOS Next Applications Applicable...

Mutual invocation between application side and front-end pages (C/C++) Native JSBridge Implementation in HarmonyOS Next Applications Applicable Architecture This solution is suitable for applicatio...

#harmonyosnext

Origin | Interest | Match

0 0 0 0
Preview
Adaptation Rules from TypeScript to ArkTS (4) # ArkTS Constraints on TypeScript Features ## No Support for Conditional Types * **Rule** : arkts-no-conditional-types * **Severity** : Error * **Description** : ArkTS does not support conditional type aliases. Introduce new types with explicit constraints or rewrite logic using Object. * **TypeScript Example** : type X<T> = T extends number ? T : never; type Y<T> = T extends Array<infer Item> ? Item : never; * **ArkTS Example** : // Provide explicit constraints in type aliases type X1<T extends number> = T; // Rewrite with Object, with less type control and a need for more type checks type X2<T> = Object; // Item must be used as a generic parameter and correctly instantiable type YI<Item, T extends Array<Item>> = Item; ## No Support for Field Declarations in Constructors * **Rule** : arkts-no-ctor-prop-decls * **Severity** : Error * **Description** : ArkTS does not support declaring class fields within constructors. Declare these fields within the class. * **TypeScript Example** : class Person { constructor( protected ssn: string, private firstName: string, private lastName: string ) { this.ssn = ssn; this.firstName = firstName; this.lastName = lastName; } getFullName(): string { return this.firstName + ' ' + this.lastName; } } * **ArkTS Example** : class Person { protected ssn: string; private firstName: string; private lastName: string; constructor(ssn: string, firstName: string, lastName: string) { this.ssn = ssn; this.firstName = firstName; this.lastName = lastName; } getFullName(): string { return this.firstName + ' ' + this.lastName; } } ## No Support for Constructor Signatures in Interfaces * **Rule** : arkts-no-ctor-signatures-iface * **Severity** : Error * **Description** : ArkTS does not support constructor signatures in interfaces. Use functions or methods instead. * **TypeScript Example** : interface I { new (s: string): I; } function fn(i: I) { return new i('hello'); } * **ArkTS Example** : interface I { create(s: string): I; } function fn(i: I) { return i.create('hello'); } ## No Support for Index Access Types * **Rule** : arkts-no-aliases-by-index * **Severity** : Error * **Description** : ArkTS does not support index access types. ## No Support for Field Access by Index * **Rule** : arkts-no-props-by-index * **Severity** : Error * **Description** : ArkTS does not support dynamic field declaration or access. You can only access fields declared in the class or inherited visible fields. Accessing other fields will result in a compile - time error. * **TypeScript Example** : class Point { x: string = ''; y: string = ''; } let p: Point = { x: '1', y: '2' }; console.log(p['x']); class Person { name: string = ''; age: number = 0; [key: string]: string | number; } let person: Person = { name: 'John', age: 30, email: '***@example.com', phoneNumber: '18*********', }; * **ArkTS Example** : class Point { x: string = ''; y: string = ''; } let p: Point = { x: '1', y: '2' }; console.log(p.x); class Person { name: string; age: number; email: string; phoneNumber: string; constructor(name: string, age: number, email: string, phoneNumber: string) { this.name = name; this.age = age; this.email = email; this.phoneNumber = phoneNumber; } } let person = new Person('John', 30, '***@example.com', '18*********'); console.log(person['name']); // Compile - time error console.log(person.unknownProperty); // Compile - time error let arr = new Int32Array(1); arr[0];
0 0 0 0
Preview
Adaptation Rules from TypeScript to ArkTS (4) # ArkTS Constraints on TypeScript Features ## No Support for Conditional Types * **Rule** : arkts-no-conditional-types * **Severity** : Error * **Description** : ArkTS does not support conditional type aliases. Introduce new types with explicit constraints or rewrite logic using Object. * **TypeScript Example** : type X<T> = T extends number ? T : never; type Y<T> = T extends Array<infer Item> ? Item : never; * **ArkTS Example** : // Provide explicit constraints in type aliases type X1<T extends number> = T; // Rewrite with Object, with less type control and a need for more type checks type X2<T> = Object; // Item must be used as a generic parameter and correctly instantiable type YI<Item, T extends Array<Item>> = Item; ## No Support for Field Declarations in Constructors * **Rule** : arkts-no-ctor-prop-decls * **Severity** : Error * **Description** : ArkTS does not support declaring class fields within constructors. Declare these fields within the class. * **TypeScript Example** : class Person { constructor( protected ssn: string, private firstName: string, private lastName: string ) { this.ssn = ssn; this.firstName = firstName; this.lastName = lastName; } getFullName(): string { return this.firstName + ' ' + this.lastName; } } * **ArkTS Example** : class Person { protected ssn: string; private firstName: string; private lastName: string; constructor(ssn: string, firstName: string, lastName: string) { this.ssn = ssn; this.firstName = firstName; this.lastName = lastName; } getFullName(): string { return this.firstName + ' ' + this.lastName; } } ## No Support for Constructor Signatures in Interfaces * **Rule** : arkts-no-ctor-signatures-iface * **Severity** : Error * **Description** : ArkTS does not support constructor signatures in interfaces. Use functions or methods instead. * **TypeScript Example** : interface I { new (s: string): I; } function fn(i: I) { return new i('hello'); } * **ArkTS Example** : interface I { create(s: string): I; } function fn(i: I) { return i.create('hello'); } ## No Support for Index Access Types * **Rule** : arkts-no-aliases-by-index * **Severity** : Error * **Description** : ArkTS does not support index access types. ## No Support for Field Access by Index * **Rule** : arkts-no-props-by-index * **Severity** : Error * **Description** : ArkTS does not support dynamic field declaration or access. You can only access fields declared in the class or inherited visible fields. Accessing other fields will result in a compile - time error. * **TypeScript Example** : class Point { x: string = ''; y: string = ''; } let p: Point = { x: '1', y: '2' }; console.log(p['x']); class Person { name: string = ''; age: number = 0; [key: string]: string | number; } let person: Person = { name: 'John', age: 30, email: '***@example.com', phoneNumber: '18*********', }; * **ArkTS Example** : class Point { x: string = ''; y: string = ''; } let p: Point = { x: '1', y: '2' }; console.log(p.x); class Person { name: string; age: number; email: string; phoneNumber: string; constructor(name: string, age: number, email: string, phoneNumber: string) { this.name = name; this.age = age; this.email = email; this.phoneNumber = phoneNumber; } } let person = new Person('John', 30, '***@example.com', '18*********'); console.log(person['name']); // Compile - time error console.log(person.unknownProperty); // Compile - time error let arr = new Int32Array(1); arr[0];
0 0 0 0
Preview
Adaptation Rules from TypeScript to ArkTS (3) # ArkTS Constraints on TypeScript Features ## Use class Instead of Types with Call Signatures * **Rule** : arkts-no-call-signatures * **Severity** : Error * **Description** : ArkTS does not support call signatures in object types. Instead of using a type with a call signature, define a class with an invoke method. * **TypeScript Example** : type DescribableFunction = { description: string; (someArg: string): string; // call signature }; function doSomething(fn: DescribableFunction): void { console.log(fn.description + " returned " + fn("")); } * **ArkTS Example** : class DescribableFunction { description: string; constructor() { this.description = "desc"; } public invoke(someArg: string): string { return someArg; } } function doSomething(fn: DescribableFunction): void { console.log(fn.description + " returned " + fn.invoke("")); } doSomething(new DescribableFunction()); ## Use class Instead of Types with Construct Signatures * **Rule** : arkts-no-ctor-signatures-type * **Severity** : Error * **Description** : ArkTS does not support construct signatures in object types. Instead of using a type with a construct signature, define a class. * **TypeScript Example** : class SomeObject {} type SomeConstructor = { new (s: string): SomeObject; }; function fn(ctor: SomeConstructor) { return new ctor("hello"); } * **ArkTS Example** : class SomeObject { public f: string; constructor(s: string) { this.f = s; } } function fn(s: string): SomeObject { return new SomeObject(s); } ## Only One Static Block Allowed * **Rule** : arkts-no-multiple-static-blocks * **Severity** : Error * **Description** : ArkTS does not allow multiple static blocks in a class. Merge multiple static blocks into a single one. * **TypeScript Example** : class C { static s: string; static { C.s = "aa"; } static { C.s = C.s + "bb"; } } * **ArkTS Example** : class C { static s: string; static { C.s = "aa"; C.s = C.s + "bb"; } } ## No Support for Index Signatures * **Rule** : arkts-no-indexed-signatures * **Severity** : Error * **Description** : ArkTS does not support index signatures. Use arrays instead. * **TypeScript Example** : interface StringArray { [index: number]: string; } function getStringArray(): StringArray { return ["a", "b", "c"]; } const myArray: StringArray = getStringArray(); const secondItem = myArray[1]; * **ArkTS Example** : class X { public f: string[] = []; } const myArray: X = new X(); myArray.f.push("a", "b", "c"); const secondItem = myArray.f[1]; ## Use Inheritance Instead of Intersection Types * **Rule** : arkts-no-intersection-types * **Severity** : Error * **Description** : ArkTS does not support intersection types. Use inheritance instead. * **TypeScript Example** : interface Identity { id: number; name: string; } interface Contact { email: string; phoneNumber: string; } type Employee = Identity & Contact; * **ArkTS Example** : interface Identity { id: number; name: string; } interface Contact { email: string; phoneNumber: string; } interface Employee extends Identity, Contact {} ## No Support for this Type * **Rule** : arkts-no-typing-with-this * **Severity** : Error * **Description** : ArkTS does not support the this type. Use explicit concrete types instead. * **TypeScript Example** : interface ListItem { getHead(): this; } class C { n: number = 0; m(c: this) { // ... } } * **ArkTS Example** : interface ListItem { getHead(): ListItem; } class C { n: number = 0; m(c: C) { // ... } }
0 0 0 0
Preview
Adaptation Rules from TypeScript to ArkTS (2) # ArkTS Constraints on TypeScript Features ## Object Property Names Must Be Valid Identifiers * **Rule** : arkts-identifiers-as-prop-names * **Severity** : Error * **Description** : In ArkTS, object property names cannot be numbers or arbitrary strings. Exceptions are string literals and string values in enums. Use property names to access class properties and numeric indices for array elements. * **TypeScript Example** : var x = { 'name': 'x', 2: '3' }; console.log(x['name']); console.log(x[2]); * **ArkTS Example** : class X { public name: string = ''; } let x: X = { name: 'x' }; console.log(x.name); let y = ['a', 'b', 'c']; console.log(y[2]); // Use Map<Object, some_type> for non - identifier keys let z = new Map<Object, string>(); z.set('name', '1'); z.set(2, '2'); console.log(z.get('name')); console.log(z.get(2)); enum Test { A = 'aaa', B = 'bbb' } let obj: Record<string, number> = { [Test.A]: 1, // String value from enum [Test.B]: 2, // String value from enum ['value']: 3 // String literal } ## No Support for Symbol() API * **Rule** : arkts-no-symbol * **Severity** : Error * **Description** : ArkTS does not support the Symbol() API due to its limited relevance in a statically - typed language. Object layout is determined at compile - time and cannot be changed at runtime. Only Symbol.iterator is supported. ## No Private Fields with # Prefix * **Rule** : arkts-no-private-identifiers * **Severity** : Error * **Description** : ArkTS does not support private fields declared with the # prefix. Use the private keyword instead. * **TypeScript Example** : class C { #foo: number = 42; } * **ArkTS Example** : class C { private foo: number = 42; } ## Unique Names for Types and Namespaces * **Rule** : arkts-unique-names * **Severity** : Error * **Description** : Types (classes, interfaces, enums), and namespaces must have unique names that do not conflict with other identifiers like variable or function names. * **TypeScript Example** : let X: string; type X = number[]; // Type alias shares name with variable * **ArkTS Example** : let X: string; type T = number[]; // Renamed to avoid conflict ## Use let Instead of var * **Rule** : arkts-no-var * **Severity** : Error * **Description** : ArkTS prefers let for variable declaration due to its block - scope and reduced error risk. * **TypeScript Example** : function f(shouldInitialize: boolean) { if (shouldInitialize) { var x = 'b'; } return x; } console.log(f(true)); // b console.log(f(false)); // undefined let upperLet = 0; { var scopedVar = 0; let scopedLet = 0; upperLet = 5; } scopedVar = 5; // Visible scopedLet = 5; // Compile - time error * **ArkTS Example** : function f(shouldInitialize: boolean): string { let x: string = 'a'; if (shouldInitialize) { x = 'b'; } return x; } console.log(f(true)); // b console.log(f(false)); // a let upperLet = 0; let scopedVar = 0; { let scopedLet = 0; upperLet = 5; } scopedVar = 5; scopedLet = 5; // Compile - time error ## Explicit Types Instead of any or unknown * **Rule** : arkts-no-any-unknown * **Severity** : Error * **Description** : ArkTS does not support the any and unknown types. Declare variables with explicit types. * **TypeScript Example** : let value1: any; value1 = true; value1 = 42; let value2: unknown; value2 = true; value2 = 42; * **ArkTS Example** : let value_b: boolean = true; // Or let value_b = true let value_n: number = 42; // Or let value_n = 42 let value_o1: Object = true; let value_o2: Object = 42;
0 0 0 0
Preview
JsonFormat is here # JSON Format Plugin ## Introduction The JSON Format plugin is a powerful tool for JSON data manipulation and conversion. It supports multiple IDEs, including IDEA, Android Studio, and DevEco Studio, making it a versatile addition to your development workflow. ## Features 1. **JSON to JavaBean** : Convert JSON data into a JavaBean class. 2. **JSON to Harmony .ets Model** : Transform JSON data into a Harmony .ets file. 3. **JavaBean to Harmony .ets Model** : Convert existing JavaBean classes into Harmony .ets files. ## Version History Here's a summary of the plugin's version updates and compatibility: Plugin Version | IDEA Version | DevEco Version | Android Studio Version | Notes ---|---|---|---|--- v1.0.2 | 2023.3.1 | 5.0.3.403 | Android Studio Jellyfish 2023.3.1 | v1.0.3 | 2023.3.1 | 5.0.3.403 | Android Studio Jellyfish 2023.3.1 | v1.0.4-deveco | 2023.3.1 | 5.0.3.501 | Android Studio Jellyfish 2023.3.1 | Deprecated v1.0.5-deveco | 2023.3.1 | 5.0.3.502 | Android Studio Jellyfish 2023.3.1 | Supports DevEco marketplace download v1.0.6 | 2023.3.1 | 5.0.3.502 | Android Studio Jellyfish 2023.3.1 | Supports DevEco marketplace download ### Notes * The plugin versions with the suffix "deveco" are specially designed for DevEco Studio. Please do not use them in IDEA or Android Studio. * Starting from version v1.0.6, the plugin supports all three conversion formats and is compatible with IDEA, Android Studio, and DevEco Studio. ## Installation You can find the plugin for download at plugins.jetbrains.com/plugin/2493. For Harmony IDE, follow these steps to install the plugin: 1. Open DevEco Studio and navigate to Settings > Plugins. 2. Click on "Install Plugin from Disk." 3. Locate the downloaded plugin file with a .jar extension and select it. 4. Click OK to start the installation process. 5. Once the installation is complete, restart your IDE. ## Usage ### Converting JSON to Harmony .ets Model 1. Create a new class file, such as User.ets. 2. Right-click in the editor and select Generate, then choose Json2ets. You can also use the shortcut keys Alt + Insert to quickly access the Json2ets option. 3. Paste your JSON string into the dialog box, enter a class name that matches the file name, and select whether to generate a class or interface. 4. Click OK to generate the corresponding .ets model. ### Examples #### Simple JSON **JSON** : { "msg": "Success", "code": 200 } **Generated Code** : export class User { msg?: string; code?: number; } #### Nested JSON **JSON** : { "msg": "Success", "code": 200, "data": { "username": "John Doe", "password": "123456" } } **Generated Code** : export class User { msg?: string; code?: number; data?: User.Data; } export namespace User { export class Data { username?: string; password?: string; } } #### JSON with List **JSON** : { "msg": "Success", "code": 200, "data": [ { "id": 12, "name": "Senior Android Engineer", "cname": " Toutiao", "size": "Series D", "salary": "40K-60K", "username": "Kimi", "title": "HR", "page": "0" }, { "id": 13, "name": "Mobile Architect", "cname": "Yinhuan Games", "size": "Series B", "salary": "15K-20K", "username": "Liu Li", "title": "Personnel Manager", "page": "0" }, { "id": 14, "name": "Java Engineer", "cname": "37 Entertainment", "size": "Series D", "salary": "25K-30K", "username": "Reiki", "title": "HR-M", "page": "0" }, { "id": 16, "name": "iOS Engineer", "cname": "Yinhuan Games Technology", "size": "Series D", "salary": "15K-20K", "username": "Ma Xiaoling", "title": "Java Programmer", "page": "0" }, { "id": 17, "name": "Java Engineer", "cname": "4399 Games Technology", "size": "Series C", "salary": "15K-20K", "username": "Ma Xiaoling", "title": "HR-M", "page": "0" } ] } **Generated Code** : export class User { msg?: string; code?: number; data?: User.Data[]; } export namespace User { export class Data { id?: number; name?: string; cname?: string; size?: string; salary?: string; username?: string; title?: string; page?: string; } }
0 0 0 0
Post image

Huawei Pura 80 Series ufficiale: stile e fotografia al top
#Fotocamere #HarmonyOS51 #HarmonyOSNext #Huawei #HuaweiPura80 #HuaweiPura80Ultra #Kirin9020 #MobileNews #Notizie #Pura80Pro #Pura80ProPlus #Pura80Ultra #Smartphone #Tech #TechNews #Tecnologia
www.ceotech.it/huawei-pura-...

1 0 0 0
Preview
ArkTS programming specification(5) # Programming Practices ## Array Traversal * **Level** : Requirement * **Description** : For array traversal, prioritize using Array object methods such as forEach(), map(), every(), filter(), find(), findIndex(), reduce(), and some(). * **Negative Example** : const numbers = [1, 2, 3, 4, 5]; const increasedByOne: number[] = []; for (let i = 0; i < numbers.length; i++) { increasedByOne.push(numbers[i] + 1); } * **Positive Example** : const numbers = [1, 2, 3, 4, 5]; const increasedByOne: number[] = numbers.map(num => num + 1); ## Assignment in Control - Flow Expressions * **Level** : Requirement * **Description** : Avoid performing assignments in control - flow expressions used in if, while, for, or ?: statements, as this can lead to unexpected behavior and poor code readability. * **Negative Example** : if (isFoo = false) { // ... } * **Positive Example** : const isFoo = someBoolean; if (isFoo) { // ... } ## Finally Blocks * **Level** : Requirement * **Description** : Avoid using return, break, continue, or throw statements in finally blocks. Unhandled exceptions in called methods can also cause premature termination of the finally block. Premature termination can affect exception propagation in try or catch blocks and method return values. * **Negative Example** : function foo() { try { // ... return 1; } catch (err) { // ... return 2; } finally { return 3; } } * **Positive Example** : function foo() { try { // ... return 1; } catch (err) { // ... return 2; } finally { console.log('XXX!'); } } ## ESObject Usage * **Level** : Suggestion * **Description** : ESObject is mainly used for type annotations in cross - language calls between ArkTS and TS/JS. Using ESObject in non - cross - language scenarios introduces unnecessary overhead. * **Negative Example** : // lib.ets export interface I { sum: number } export function getObject(value: number): I { let obj: I = { sum: value }; return obj } // app.ets import { getObject } from 'lib' let obj: ESObject = getObject(123); * **Positive Example** : // lib.ets export interface I { sum: number } export function getObject(value: number): I { let obj: I = { sum: value }; return obj } // app.ets import { getObject, I } from 'lib' let obj: I = getObject(123); ## Array Type Notation * **Level** : Suggestion * **Description** : ArkTS supports two array type notations: T[] and Array. For better readability, it is recommended to use T[]. * **Negative Example** : let x: Array<number> = [1, 2, 3]; let y: Array<string> = ['a', 'b', 'c']; * **Positive Example** : let x: number[] = [1, 2, 3]; let y: string[] = ['a', 'b', 'c'];
0 0 0 0
Preview
HarmonyOS Next IM Practical Combat: Handling So Dynamic Library Crash Issues #### Background Introduction After the IM SDK for HarmonyOS Next was integrated into the application and launched, many users reported significant app lag, particularly those with a large number of conversations and messages. Due to design flaws in the SDK's logic, receiving a message triggered a full refresh of the conversation list, which involved querying the entire database. This operation was time-consuming when there were many conversations and was originally performed on the main thread, causing the app to freeze. To address this issue, we decided to leverage HarmonyOS's Worker threads. We introduced two worker threads during app initialization: one for fetching the conversation list and another for message retrieval. This approach aimed to offload database operations from the main thread. Workers were chosen because these operations are complex, involve multiple tasks, and require background thread support. #### Problem Description After creating the worker thread as per the standard procedure and starting it during SDK initialization: this.syncConfigWorkerInstance = new worker.ThreadWorker("../workers/SyncConfigAndConvWorker.ets"); this.syncConfigWorkerInstance.onmessage = async (event) => { // Event handler } The application crashed or froze immediately after starting the worker, even though the worker thread itself did nothing. The crash occurred in a C++ shared library (`.so`) unrelated to the worker's logic, which was puzzling: Timestamp: 2025-05-07 17:12:54:794 Tid: 8025, Name: beike.imsdk.tob #00 pc 00000000001b6344 /system/lib/ld-musl-aarch64.so.1(fcf57c313493609e8c78a5f07477c358) #01 pc 00000000001b834c /system/lib/ld-musl-aarch64.so.1(pthread_cond_timedwait+188)(fcf57c313493609e8c78a5f07477c358) #02 pc 00000000000c430c /data/storage/el1/bundle/libs/arm64/libc++_shared.so(std::__n1::condition_variable::wait(std::__n1::unique_lock<std::__n1::mutex>&)+20)(cdf97be9396a35e8f4806f252f90a11320d26ec6) #03 pc 00000000000c4e9c /data/storage/el1/bundle/libs/arm64/libc++_shared.so(std::__n1::__assoc_sub_state::__sub_wait(std::__n1::unique_lock<std::__n1::mutex>&)+48)(cdf97be9396a35e8f4806f252f90a11320d26ec6) #04 pc 00000000000447f4 /data/storage/el1/bundle/libs/arm64/libmarsstn.so(4ed6d779cb9585f42f228dfc8a706399ce60a56f) #05 pc 0000000000044344 /data/storage/el1/bundle/libs/arm64/libmarsstn.so(4ed6d779cb9585f42f228dfc8a706399ce60a56f) #06 pc 00000000000d7cf0 /data/storage/el1/bundle/libs/arm64/libmarsstn.so(4ed6d779cb9585f42f228dfc8a706399ce60a56f) #07 pc 000000000006983c /data/storage/el1/bundle/libs/arm64/libmarsstn.so(4ed6d779cb9585f42f228dfc8a706399ce60a56f) #### Problem Diagnosis Initially, the crash was reproducible in a specific scenario but later became random. Disabling the dynamic library initialization or the worker thread resolved the issue. To identify the root cause, we enabled multithreading detection on a physical device: hdc shell param set persist.ark.properties 0x107c After rebooting the device and reproducing the crash, we obtained the following details: Process name: com.beike.imsdk.tob Process life time: 34s Reason: Signal: SIGABRT(SI_TKILL)@0x01317b4e00004e2a from: 20010:20020046 LastFatalMessage: [(ark_native_reference.cpp:117)(Get)] param env is not equal to its owner Fault thread info: Tid: 20010, Name: kou.imsdk.tob #00 pc 0000000000199e1c /system/lib/ld-musl-aarch64.so.1(raise+228)(6b9883f518515f73e093bce9a89a2548) #01 pc 0000000000146f8c /system/lib/ld-musl-aarch64.so.1(abort+20)(6b9883f518515f73e093bce9a89a2548) #02 pc 0000000000056fac /system/lib64/platformsdk/libace_napi.z.so(ArkNativeReference::Get(NativeEngine*)+476)(edf034e044dbf26f955142c343577527) #03 pc 000000000005f0a0 /system/lib64/platformsdk/libace_napi.z.so(napi_get_reference_value+48)(edf034e044dbf26f955142c343577527) #04 pc 00000000000ea354 /data/storage/el1/bundle/libs/arm64/libmarsstn.so(160beef25288e9539a33ed6f307aa362ceb17fc1) #05 pc 0000000000070754 /system/lib64/platformsdk/libace_napi.z.so(NativeSafeAsyncWork::ProcessAsyncHandle()+596) Using the `addr2line` tool, we traced the crash to the `napi_get_reference_value` call in `libmarsstn.so`, where the `env` parameter was invalid. Further investigation revealed that the `env` was cached from the main thread during SO initialization (performed on the main thread). Adding logs confirmed that the crash occurred when the main thread used this cached `env`, which had been overwritten by a worker thread: Logs showed that the `napi_module_register` function in the SO library was being called from worker threads, overwriting the cached `mainEnv_` (a singleton in C++). In HarmonyOS Next, Worker threads are isolated with their own memory spaces, similar to separate processes. Each Worker thread loads the SO library independently, leading to multiple initializations. #### Solution To resolve the issue, we ensured that `mainEnv_` is initialized only once, during the first call from the main thread. We used `std::atomic` for thread-safe initialization: std::atomic<bool> flag{false}; bool expected = false; if (flag.compare_exchange_strong(expected, true)) { napi_status status; int32_t ret; auto context = MarsNapiManager::getInstance(); if (context) { context->mainEnv_ = env; context->mainThreadId = std::this_thread::get_id(); auto marsNapi = context->getMarsNapi(); marsNapi->Export(env, exports); } } else { xdebug2(TSF"napi-->initXComponent not first"); } #### Another Multithreading Issue When passing SDK configuration parameters to the worker thread using HarmonyOS Next's Sendable mechanism, the application crashed with the error: TypeError: Cannot set sendable property with mismatched type The crash occurred during `postMessage`. Initially, we serialized the object to JSON to bypass the issue. Further investigation revealed that the demo used class instances (which implemented Sendable), while the app used Record objects, which lacked Sendable implementation. #### Conclusion This case highlights critical differences between HarmonyOS Next's Worker threads and traditional thread models: each Worker thread loads SO libraries independently, causing the main thread's `env` cached in C++ singletons to be overwritten. Key findings: 1. **Root Cause** : The main thread's cached `env` (`mainEnv_`) was overwritten by worker threads during `napi_module_register`, leading to invalid `env` usage in `napi_get_reference_value`. 2. **Thread Characteristics** : Worker threads have strong memory isolation, similar to separate processes, causing SO libraries to be reloaded. 3. **Solution** : Use `std::atomic` to ensure `mainEnv_` is initialized only once on the main thread, with `compare_exchange_strong` for thread safety. 4. **Derived Issue** : Cross-thread data transfer must strictly follow the Sendable protocol; non-Sendable objects (e.g., Record) should be serialized to JSON. This case underscores two critical considerations in HarmonyOS multithreading: **thread safety during SO library initialization** and **strict adherence to cross-thread data transfer protocols**.
0 0 0 0
Preview
Harmonyos Ark UI network request # Adding Internet Permissions and Creating HTTPS Requests ## Adding Internet Permissions To enable internet access, add the following to your `module.json5`: "requestPermissions": [ { "name": "ohos.permission.INTERNET" } ] ## Creating HTTPS Requests HTTPS is a secure transport protocol that encrypts data between client and server using TLS/SSL. Here's how to create an HTTPS request and log the response. ### HTTP Request Utility Class In `OkHttpUtil.ts`, create an HTTP request task with `createHttp()` and send the request with `request()`. The method supports parameters for URL, options (to set request method, headers, timeouts, etc.), and a callback. import http from '@ohos.net.http'; import Constants, { ContentType } from '../constant/Constants'; import Logger from './Logger'; import { NewsData } from '../viewmodel/NewsData'; export function httpRequestGet(url: string) { return httpRequest(url, http.RequestMethod.GET); } export function httpRequestPost(url: string, params?: NewsData) { return httpRequest(url, http.RequestMethod.POST, params); } function httpRequest(url: string, method: http.RequestMethod, params?: NewsData) { let httpRequest = http.createHttp(); let responseResult = httpRequest.request(url, { method: method, readTimeout: Constants.HTTP_READ_TIMEOUT, // Optional, default is 60000ms header: { 'Content-Type': ContentType.JSON }, connectTimeout: Constants.HTTP_READ_TIMEOUT, // Optional, default is 60000ms extraData: params // Request parameters }); return responseResult.then((value: http.HttpResponse) => { Logger.error("Request status --> " + value.responseCode); if (value.responseCode === 200) { Logger.error("Request succeeded"); let getResult = value.result; Logger.error('Response data:', JSON.stringify(getResult)); return getResult; } }).catch((err) => { return ""; }); } ### Logger Utility Class import hilog from '@ohos.hilog'; class Logger { private domain: number; private prefix: string; private format: string = '%{public}s, %{public}s'; constructor(prefix: string = 'MyApp', domain: number = 0xFF00) { this.prefix = prefix; this.domain = domain; } debug(...args: string[]): void { hilog.debug(this.domain, this.prefix, this.format, args); } info(...args: string[]): void { hilog.info(this.domain, this.prefix, this.format, args); } warn(...args: string[]): void { hilog.warn(this.domain, this.prefix, this.format, args); } error(...args: string[]): void { hilog.error(this.domain, this.prefix, this.format, args); } } export default new Logger('HTTPS', 0xFF00); ### Triggering Requests in the View Display a button in the view that triggers the HTTPS request when clicked. import webView from '@ohos.web.webview'; import http from '@ohos.net.http'; import httpGet from '../common/utils/HttpUtil'; import StyleConstant from '../common/constant/StyleConstant'; import CommonConstant from '../common/constant/CommonConstants'; import { httpRequestGet } from '../common/utils/OKhttpUtil'; @Entry @Component struct WebPage { controller: webView.WebviewController = new webView.WebviewController(); @State buttonName: Resource = $r('app.string.request_button_name'); @State webVisibility: Visibility = Visibility.Hidden; @State webSrc: string = CommonConstant.DISH; build() { Column() { Row() { Image($r('app.media.ic_network_global')) .height($r('app.float.image_height')) .width($r('app.float.image_width')) TextInput({ placeholder: $r('app.string.input_address'), text: this.webSrc }) .height($r('app.float.text_input_height')) .layoutWeight(1) .backgroundColor(Color.White) .onChange((value: string) => { this.webSrc = value; }) } .margin({ top: $r('app.float.default_margin'), left: $r('app.float.default_margin'), right: $r('app.float.default_margin') }) .height($r('app.float.default_row_height')) .backgroundColor(Color.White) .borderRadius($r('app.float.border_radius')) .padding({ left: $r('app.float.default_padding'), right: $r('app.float.default_padding') }) Row() { Web({ src: this.webSrc, controller: this.controller }) .zoomAccess(true) .height(StyleConstant.FULL_HEIGHT) .width(StyleConstant.FULL_WIDTH) } .visibility(this.webVisibility) .height(StyleConstant.WEB_HEIGHT) .width(StyleConstant.FULL_WIDTH) .align(Alignment.Top) Row() { Button(this.buttonName) .fontSize($r('app.float.button_font_size')) .width(StyleConstant.BUTTON_WIDTH) .height($r('app.float.button_height')) .fontWeight(FontWeight.Bold) .onClick(() => { this.onRequest(); }) } .height($r('app.float.default_row_height')) } .width(StyleConstant.FULL_WIDTH) .height(StyleConstant.FULL_HEIGHT) .backgroundImage($r('app.media.ic_background_image', ImageRepeat.NoRepeat)) .backgroundImageSize(ImageSize.Cover) } async onRequest() { httpRequestGet(CommonConstant.DISH).then((data) => { console.log("Data received: " + data); }); } }
0 0 0 0
Preview
Harmonyos Ark UI network request # Adding Internet Permissions and Creating HTTPS Requests ## Adding Internet Permissions To enable internet access, add the following to your `module.json5`: "requestPermissions": [ { "name": "ohos.permission.INTERNET" } ] ## Creating HTTPS Requests HTTPS is a secure transport protocol that encrypts data between client and server using TLS/SSL. Here's how to create an HTTPS request and log the response. ### HTTP Request Utility Class In `OkHttpUtil.ts`, create an HTTP request task with `createHttp()` and send the request with `request()`. The method supports parameters for URL, options (to set request method, headers, timeouts, etc.), and a callback. import http from '@ohos.net.http'; import Constants, { ContentType } from '../constant/Constants'; import Logger from './Logger'; import { NewsData } from '../viewmodel/NewsData'; export function httpRequestGet(url: string) { return httpRequest(url, http.RequestMethod.GET); } export function httpRequestPost(url: string, params?: NewsData) { return httpRequest(url, http.RequestMethod.POST, params); } function httpRequest(url: string, method: http.RequestMethod, params?: NewsData) { let httpRequest = http.createHttp(); let responseResult = httpRequest.request(url, { method: method, readTimeout: Constants.HTTP_READ_TIMEOUT, // Optional, default is 60000ms header: { 'Content-Type': ContentType.JSON }, connectTimeout: Constants.HTTP_READ_TIMEOUT, // Optional, default is 60000ms extraData: params // Request parameters }); return responseResult.then((value: http.HttpResponse) => { Logger.error("Request status --> " + value.responseCode); if (value.responseCode === 200) { Logger.error("Request succeeded"); let getResult = value.result; Logger.error('Response data:', JSON.stringify(getResult)); return getResult; } }).catch((err) => { return ""; }); } ### Logger Utility Class import hilog from '@ohos.hilog'; class Logger { private domain: number; private prefix: string; private format: string = '%{public}s, %{public}s'; constructor(prefix: string = 'MyApp', domain: number = 0xFF00) { this.prefix = prefix; this.domain = domain; } debug(...args: string[]): void { hilog.debug(this.domain, this.prefix, this.format, args); } info(...args: string[]): void { hilog.info(this.domain, this.prefix, this.format, args); } warn(...args: string[]): void { hilog.warn(this.domain, this.prefix, this.format, args); } error(...args: string[]): void { hilog.error(this.domain, this.prefix, this.format, args); } } export default new Logger('HTTPS', 0xFF00); ### Triggering Requests in the View Display a button in the view that triggers the HTTPS request when clicked. import webView from '@ohos.web.webview'; import http from '@ohos.net.http'; import httpGet from '../common/utils/HttpUtil'; import StyleConstant from '../common/constant/StyleConstant'; import CommonConstant from '../common/constant/CommonConstants'; import { httpRequestGet } from '../common/utils/OKhttpUtil'; @Entry @Component struct WebPage { controller: webView.WebviewController = new webView.WebviewController(); @State buttonName: Resource = $r('app.string.request_button_name'); @State webVisibility: Visibility = Visibility.Hidden; @State webSrc: string = CommonConstant.DISH; build() { Column() { Row() { Image($r('app.media.ic_network_global')) .height($r('app.float.image_height')) .width($r('app.float.image_width')) TextInput({ placeholder: $r('app.string.input_address'), text: this.webSrc }) .height($r('app.float.text_input_height')) .layoutWeight(1) .backgroundColor(Color.White) .onChange((value: string) => { this.webSrc = value; }) } .margin({ top: $r('app.float.default_margin'), left: $r('app.float.default_margin'), right: $r('app.float.default_margin') }) .height($r('app.float.default_row_height')) .backgroundColor(Color.White) .borderRadius($r('app.float.border_radius')) .padding({ left: $r('app.float.default_padding'), right: $r('app.float.default_padding') }) Row() { Web({ src: this.webSrc, controller: this.controller }) .zoomAccess(true) .height(StyleConstant.FULL_HEIGHT) .width(StyleConstant.FULL_WIDTH) } .visibility(this.webVisibility) .height(StyleConstant.WEB_HEIGHT) .width(StyleConstant.FULL_WIDTH) .align(Alignment.Top) Row() { Button(this.buttonName) .fontSize($r('app.float.button_font_size')) .width(StyleConstant.BUTTON_WIDTH) .height($r('app.float.button_height')) .fontWeight(FontWeight.Bold) .onClick(() => { this.onRequest(); }) } .height($r('app.float.default_row_height')) } .width(StyleConstant.FULL_WIDTH) .height(StyleConstant.FULL_HEIGHT) .backgroundImage($r('app.media.ic_background_image', ImageRepeat.NoRepeat)) .backgroundImageSize(ImageSize.Cover) } async onRequest() { httpRequestGet(CommonConstant.DISH).then((data) => { console.log("Data received: " + data); }); } }
0 0 0 0
Preview
Basic usage and tips of the HarmonyOS lightweight database DatabaseHelper # Creating a Database and Performing Operations ## Creating a Database To create a database, use the DatabaseHelper utility class. By calling the getPreferences(String name) method of DatabaseHelper, you can obtain a Preferences instance corresponding to a specific file name. This Preferences instance allows you to perform various database operations. The DatabaseHelper constructor requires a context parameter, which can be obtained by calling getContext() on an Ability or AbilitySlice instance, as both implement the ohos.app.Context interface. Preferences data is stored in files, so you must specify a non - empty file name without any path. The default storage directory can be retrieved using Context.getPreferencesDir(). **Code:** DatabaseHelper databaseHelper = new DatabaseHelper(context); String filename = "pdb"; Preferences preferences = databaseHelper.getPreferences(filename); ## Writing Data Once you have the input from the text field, you can store the data using the put methods of the Preferences instance when the button is clicked. Use Preferences.putString(String var1, String var2) and Preferences.putInt(String var1, int var2) to write data. Call flush() or flushSync() to persist the Preferences instance. flush() immediately updates the in - memory Preferences object and writes changes to disk asynchronously, whereas flushSync() performs a synchronous write. Avoid calling flushSync() from the main thread to prevent UI lag. **Code:** private void btnWrite() { btnWrite.setClickedListener(new Component.ClickedListener() { @Override public void onClick(Component component) { String fruit = textFiledFruit.getText(); try { int number = Integer.parseInt(textFiledNumber.getText()); preferences.putInt("number", number); preferences.putString("fruit", fruit); preferences.flush(); new ToastDialog(context).setText("Write to DB file success").show(); } catch (NumberFormatException e) { new ToastDialog(context).setText("Please input number in Number row").show(); } } }); } ## Reading Data Retrieve stored data using the get methods of Preferences. Use Preferences.getString(String var1, String var2) and Preferences.getInt(String var1, int var2), providing a key to get the corresponding value. If the key does not exist, a default value is returned, preventing potential exceptions. **Code:** private void btnRead() { btnRead.setClickedListener(new Component.ClickedListener() { @Override public void onClick(Component component) { String string = String.format(Locale.ENGLISH, "Fruit: %s, Number: %d", preferences.getString("fruit", ""), preferences.getInt("number", 0)); new ToastDialog(context).setText(string).show(); } }); } ## Deleting a Database Delete a specific file using DatabaseHelper.deletePreferences(String name). After deletion, do not use the Preferences instance for further operations to avoid data inconsistency. For example, to delete the file named "pdb": **Code:** private void btnDelete() { btnDelete.setClickedListener(new Component.ClickedListener() { @Override public void onClick(Component component) { if (databaseHelper.deletePreferences(filename)) { preferences.clear(); new ToastDialog(context).setText("Delete DB file success").show(); } else { new ToastDialog(context).setText("Delete DB file failed").show(); } } }); } **Note:** The lightweight preference database supports file creation, movement, data querying, insertion, deletion, and allows observers to monitor data changes. ## Caching List Data Since the lightweight DatabaseHelper cannot directly store lists, convert the list to a JSON string and store it. When retrieving, parse the JSON string back to a list. ### Storing a List **Code:** public static void putSelectBean(Context context, List<UserBean> phoneList, String key) { databaseHelper = new DatabaseHelper(context); preferences = databaseHelper.getPreferences(filename); Gson gson = new Gson(); String json = gson.toJson(phoneList); preferences.putString(key, json); preferences.flush(); } ### Reading a List **Code:** public static List<UserBean> getSelectBean(Context context, String key) { databaseHelper = new DatabaseHelper(context); preferences = databaseHelper.getPreferences(filename); Gson gson = new Gson(); String json = preferences.getString(key, null); Type type = new TypeToken<List<UserBean>>() {}.getType(); List<UserBean> arrayList = gson.fromJson(json, type); return arrayList; } ### Storing a List **Code:** private void btnSavelist() { btnsavelist.setClickedListener(new Component.ClickedListener() { @Override public void onClick(Component component) { UserBean userBean = new UserBean(); userBean.setUsername("test"); userBean.setPassword("123456"); List<UserBean> datalist = new ArrayList<>(); datalist.add(userBean); DataBaseUtil.putSelectBean(context, datalist, "datalist"); new ToastDialog(context).setText("Write success").show(); } }); } ### Reading a List **Code:** private void btnReadList() { btn_read_list.setClickedListener(new Component.ClickedListener() { @Override public void onClick(Component component) { List<UserBean> getData = DataBaseUtil.getSelectBean(context, "datalist"); UserBean userBean = getData.get(0); new ToastDialog(context).setText(userBean.getUsername() + userBean.getPassword()).show(); } }); } ## Simplifying DatabaseHelper Usage with a Utility Class ### Storing Data **Code:** private static String filename = "pdb"; private static Preferences preferences; private static DatabaseHelper databaseHelper; public static void setParam(Context context, String key, Object object) { String type = "String"; if (object != null) { type = object.getClass().getSimpleName(); } databaseHelper = new DatabaseHelper(context); preferences = databaseHelper.getPreferences(filename); if ("String".equals(type)) { preferences.putString(key, (String) object); } else if ("Integer".equals(type) || "int".equals(type)) { preferences.putInt(key, (Integer) object); } else if ("Boolean".equals(type) || "boolean".equals(type)) { preferences.putBoolean(key, (Boolean) object); } else if ("Float".equals(type) || "float".equals(type)) { preferences.putFloat(key, (Float) object); } else if ("Long".equals(type) || "long".equals(type)) { preferences.putLong(key, (Long) object); } preferences.flush(); } ### Reading Data **Code:** public static Object getParam(Context context, String key, Object defaultObject) { String type = "String"; if (defaultObject != null) { type = defaultObject.getClass().getSimpleName(); } databaseHelper = new DatabaseHelper(context); preferences = databaseHelper.getPreferences(filename); if ("String".equals(type)) { return preferences.getString(key, (String) defaultObject); } else if ("Integer".equals(type) || "int".equals(type)) { return preferences.getInt(key, (Integer) defaultObject); } else if ("Boolean".equals(type) || "boolean".equals(type)) { return preferences.getBoolean(key, (Boolean) defaultObject); } else if ("Float".equals(type) || "float".equals(type)) { return preferences.getFloat(key, (Float) defaultObject); } else if ("Long".equals(type) || "long".equals(type)) { return preferences.getLong(key, (Long) defaultObject); } return null; } ### Using the Utility Class **Code:** private void btnSavetoutils() { btnsave_toutils.setClickedListener(new Component.ClickedListener() { @Override public void onClick(Component component) { String fruit = textFiledFruit.getText(); try { int number = Integer.parseInt(textFiledNumber.getText()); DataBaseUtil.setParam(context, "number", number); DataBaseUtil.setParam(context, "fruit", fruit); new ToastDialog(context).setText("Write success").show(); } catch (NumberFormatException e) { new ToastDialog(context).setText("Please input number in Number row").show(); } } }); }
0 0 0 0
Preview
Tutorial on implementing anti-wechat Chat UI Effects # MainAbility Layout File and Code Implementation ## Layout File Here's the layout file for MainAbility: <?xml version="1.0" encoding="utf-8"?> <DependentLayout xmlns:ohos="http://schemas.huawei.com/res/ohos" ohos:height="match_parent" ohos:width="match_parent" ohos:alignment="center" ohos:orientation="vertical"> <DependentLayout ohos:id="$+id:company_page_dl" ohos:height="50vp" ohos:width="match_parent" ohos:orientation="horizontal" ohos:align_parent_bottom="true"> <Button ohos:id="$+id:main_my_btn" ohos:width="match_content" ohos:height="match_content" ohos:text="Send" ohos:text_size="35vp" ohos:align_parent_right="true" ohos:background_element="$graphic:background_btn"> </Button> <TextField ohos:id="$+id:main_textfiled" ohos:width="match_parent" ohos:height="match_parent" ohos:hint="Enter your message" ohos:vertical_center="true" ohos:text_size="50" ohos:left_of="$id:main_my_btn" ohos:layout_alignment="left"> </TextField> </DependentLayout> <ListContainer ohos:above="$id:company_page_dl" ohos:id="$+id:main_list" ohos:height="match_parent" ohos:width="match_parent"> </ListContainer> </DependentLayout> In this layout file, we have a ListContainer to display sent and received messages, a TextField for user input, and a Button to trigger the sending action. ## Logic Code ### Initializing Views private void initview() { listContainer = (ListContainer) findComponentById(ResourceTable.Id_main_list); textField = (TextField) findComponentById(ResourceTable.Id_main_textfiled); mainbtn = (Button) findComponentById(ResourceTable.Id_main_my_btn); mainbtn.setClickedListener(this); myProvider = new MyProvider(data, getAbility()); listContainer.setItemProvider(myProvider); myProvider.notifyDataChanged(); // Refresh ListView display when new messages arrive } ### Initializing Default Messages private void initMsg() { Msg msg1 = new Msg("Hello", Msg.RECEIVED); data.add(msg1); Msg msg2 = new Msg("Hi there", Msg.SENT); data.add(msg2); Msg msg3 = new Msg("Nice to meet you", Msg.RECEIVED); data.add(msg3); } ### Handling User Input @Override public void onClick(Component component) { content = textField.getText().toString(); switch (component.getId()) { case ResourceTable.Id_main_my_btn: if (!flag) { Msg msg = new Msg(content, Msg.SENT); data.add(msg); flag = true; } else { Msg msg = new Msg(content, Msg.RECEIVED); data.add(msg); flag = false; } myProvider.notifyDataChanged(); // Refresh ListView display when new messages arrive textField.setText(""); // Clear the input field break; default: break; } } A boolean flag is used to alternate between sending and receiving messages. ### Message Class package com.example.imdemo.bean; public class Msg { public static final int RECEIVED = 0; // Received a message public static final int SENT = 1; // Sent a message private String content; // Message content private int type; // Message type public Msg(String content, int type) { this.content = content; this.type = type; } public String getContent() { return content; } public int getType() { return type; } } ### Adapter Item Layout (item.xml) <?xml version="1.0" encoding="utf-8"?> <DirectionalLayout xmlns:ohos="http://schemas.huawei.com/res/ohos" ohos:height="match_content" ohos:width="match_parent" ohos:orientation="vertical"> <DirectionalLayout ohos:id="$+id:left_layout" ohos:height="match_content" ohos:width="match_content" ohos:layout_alignment="left" ohos:background_element="$graphic:background_blue" ohos:left_margin="5vp" ohos:visibility="visible" ohos:top_margin="10vp"> <Text ohos:id="$+id:left_msg" ohos:height="match_content" ohos:width="match_content" ohos:text="Test message" ohos:text_color="#fff" ohos:text_size="20vp" ohos:margin="10vp"> </Text> </DirectionalLayout> <DirectionalLayout ohos:id="$+id:right_Layout" ohos:height="match_content" ohos:width="match_content" ohos:layout_alignment="right" ohos:background_element="$graphic:background_red" ohos:right_margin="5vp" ohos:visibility="visible"> <Text ohos:id="$+id:right_msg" ohos:height="match_content" ohos:width="match_content" ohos:text="Test message" ohos:text_color="#fff" ohos:text_size="20vp" ohos:margin="10vp"> </Text> </DirectionalLayout> </DirectionalLayout> The layout includes two DirectionalLayouts for displaying messages on the left and right sides, representing received and sent messages respectively. The link you provided earlier couldn't be parsed successfully due to network issues. This might be related to the link itself or a network problem. You can check the validity of the link and try again.
0 0 0 0
Preview
Multi-Device Adaptation and Responsive Design Best Practices HarmonyOS Next aims to achieve "multi-device collaboration and seamless experience." Apps need to adapt to phones, tablets, watches, car systems, and more. This article details adaptation principles, responsive layout methods, device capability grading, common issues, and official resources to help developers deliver high-quality cross-device experiences. ## 1. The Importance of Multi-Device Adaptation * Enhance user experience: Different devices have varying screen sizes and interaction methods; good adaptation ensures beautiful UI and smooth operation. * Expand user base: Supporting multiple devices covers more scenarios and increases market competitiveness. * Meet platform review requirements: HarmonyOS Next emphasizes multi-device adaptation; poor adaptation may affect app approval. ## 2. Adaptation Principles and Process 1. **Responsive Design First** * Use flexible layouts (Flex, Grid, etc.) to automatically adjust component size and arrangement based on screen size. * Avoid absolute positioning and fixed sizes to improve UI adaptability. 2. **Resolution and Density Adaptation** * Use relative units (vp, fp) to ensure consistent display across resolutions. * Provide multiple sets of icons and images for different DPI devices. 3. **Interaction Method Adaptation** * Optimize UI and flows for touch, rotary, voice, and other interaction types. 4. **Device Capability Grading** * Classify devices as basic, standard, or enhanced based on performance and features; allocate features and UI complexity accordingly. * Detect device type in code and dynamically load adaptation resources. 5. Develop Once, Deploy Everywhere * The official site provides various components and adaptation solutions for phones, tablets, PCs, etc. * Refer to official multi-device adaptation cases. ## 3. Responsive Layout Methods * **Flex Layout** : For horizontal/vertical adaptive arrangement, commonly used in main content and toolbars. * **Grid Layout** : For complex UI partitioning, supports multi-row/column adaptation. * **Media Queries** : Switch layouts based on screen width, orientation, etc. * **Component Reuse** : Encapsulate common UI as components for efficiency and consistency. > **Tip** : HarmonyOS ArkUI offers rich responsive layout components; use official recommendations first. ## 4. Device Capability Grading in Practice * **Basic Devices** : Only core features, simple UI, suitable for low-end phones, watches, etc. * **Standard Devices** : Full features and standard interactions, for mainstream phones/tablets. * **Enhanced Devices** : Multi-window, split-screen, collaboration, for high-end tablets, car systems. * Detect device type via API and adjust features/UI dynamically. ## 5. Common Issues and Tips * **UI Misalignment/Overflow** : Use flexible layouts, avoid fixed width/height. * **Blurry/Distorted Images** : Provide multi-resolution resources, use relative units. * **Inconsistent Interaction** : Optimize logic for each device, avoid "one-size-fits-all." * **Missed Adaptation** : Always test on multiple real devices before release. ## 6. Official Reference Links * HarmonyOS Next Official Docs * ArkUI Layout & Adaptation Guide * Huawei Developer Alliance Account Center ## 7. Summary Multi-device adaptation and responsive design are core skills for HarmonyOS Next app development. Use official responsive layout solutions, combine with device grading to dynamically adjust features and UI, and ensure a great experience on all devices. Consult official docs or the community for adaptation issues and keep improving product quality.
0 0 0 0
Preview
Harmonyos Development (XI) : Implementation of the Page for Posting Job Information # Developing a Job Posting Page with ArkTS Here's a complete implementation of a job posting page using ArkTS for HarmonyOS apps. This page allows enterprise users to publish new job positions. ## Code Explanation ### 1. Import Modules import { CompanyDetailModel, CompanyDetailModelData } from '../model/CompanyDetailModel'; import Logger from '../Utils/Logger'; import { httpRequestGet, httpRequestPost } from '../Utils/HttpUtils'; import { router } from '@kit.ArkUI'; import prompt from '@ohos.promptAction'; import { AddpositionModel } from '../model/AddpositionModel'; import uri from '@ohos.uri'; We've imported several modules for company details, logging, HTTP requests, routing, prompts, and job position models. ### 2. Define Style Extensions @Extend(TextInput) function inputStyle() { .placeholderColor("#99182431") .height(45) .fontSize(18) .backgroundColor("#F1F3F5") .width('100%') .padding({ left: 0 }) .margin({ top: 12 }) } @Extend(Line) function lineStyle() { .width('100%') .height(1) .backgroundColor("#FF131416") } @Extend(Text) function textStyle() { .fontColor("#FF0C0C0C") .fontSize(18) .fontWeight(FontWeight.Medium) } Defined three style extension functions: `inputStyle` for `TextInput`, `lineStyle` for `Line`, and `textStyle` for `Text` components. ### 3. Define Job Posting Component @Entry @Component struct PostaPosition { @State name: string = ""; @State cname: string = ""; @State positionsize: string = ""; @State salary: string = ""; @State username: string = ""; @State title: string = ""; private addPosition: string = "********"; async addposition() { if (this.name === '' || this.cname === '' || this.positionsize === '' || this.salary === '' || this.username === '' || this.title === '') { prompt.showToast({ message: "Input cannot be empty" }); } else { const neturl = new uri.URI(this.addPosition) .addQueryValue("name", this.name) .addQueryValue("cname", this.cname) .addQueryValue("size", this.positionsize) .addQueryValue("salary", this.salary) .addQueryValue("username", this.username) .addQueryValue("title", this.title) .toString(); Logger.error("Request neturl - > " + neturl); await httpRequestGet(neturl).then((data) => { console.log("data ---> " + data); let addpositionModel: AddpositionModel = JSON.parse(data.toString()); let msg = addpositionModel.msg; if (addpositionModel.code == 200) { prompt.showToast({ message: msg }); // router.pushUrl({ // url: "pages/Home" // }); } else { prompt.showToast({ message: msg }); } }); } } } * Created a PostaPosition component for publishing job positions * Used @State to define multiple state variables for storing user input job information * Defined addPosition for the API endpoint * In the addposition method, checked if user input is empty, displayed a message if it is; otherwise, constructed the API URL, called httpRequestGet to submit job information, and prompted the user based on the response ### 4. Page Layout build() { Column() { RelativeContainer() { Image($r('app.media.bossback')).width(20).height(20) .onClick(() => { router.back(); }).alignRules({ 'top': { 'anchor': '__container__', 'align': VerticalAlign.Top }, 'left': { 'anchor': '__container__', 'align': HorizontalAlign.Start } }).margin({ left: 5, top: 7 }); Text("Add Position Information") .fontSize(25) .fontWeight(FontWeight.Medium) .fontColor(Color.White) .alignRules({ center: { anchor: '__container__', align: VerticalAlign.Center }, middle: { anchor: '__container__', align: HorizontalAlign.Center } }); }.height(40) .width("100%") .backgroundColor(Color.Green); Row() { Row() { Text("Position Information").textStyle(); }.width(100).height("100%") .justifyContent(FlexAlign.Center); TextInput({ placeholder: "Please enter position information" }) .maxLength(20) .type(InputType.Normal) .inputStyle() .onChange((value: string) => { this.name = value; }).margin({ left: 20 }); }.width("100%").height(50) .justifyContent(FlexAlign.Start) Line().lineStyle(); // Other input fields and line styles are similar, omitted... Button("Submit") .width("90%") .height(40) .fontSize(16) .fontWeight(FontWeight.Medium) .backgroundColor("#007DFF") .margin({ top: 47, bottom: 12 }) .onClick(() => { this.addposition(); }); }.backgroundColor("#F1F3F5") .height('100%') .width('100%'); } * Used Column and RelativeContainer to build the UI * Created a header showing "Add Position Information" with a back button * Used Row and TextInput for each job information field (e.g., position info, company name, size, salary range, contact person, title) * Implemented a Button for submission, which calls the addposition method when clicked ### 5. PositionListModel: Provides Type Safety and Structured Data Handling export class PositionListModel { msg?: string = ""; code?: number = 0; data: Array<PositionListModelData> = []; } export class PositionListModelData { id?: number = 0; name?: string = ""; cname?: string = ""; size?: string = ""; salary?: string = ""; username?: string = ""; title?: string = ""; } Picture display
0 0 0 0
Preview
HarmonyOS Next 5.0.0.150: Huawei verteilt neue Beta für Mate 70 und Pura 70 Huawei hat die Public Beta 5.0.0.150 seines HarmonyOS Next für die letztjährigen Flaggschiff-Modelle Mate 70 und Pura 70 veröffentlicht.

HarmonyOS Next 5.0.0.150: Huawei verteilt neue Beta für Mate 70 und Pura 70 #harmonyos #harmonyosnext #huawei

0 0 0 0
Huawei Pura X – Điện thoại gập ngang độc đáo, trải nghiệm rộng mở! 🌿💖 Huawei Pura X - Điện Thoại Gập Ngang Đột Phá, Trải Nghiệm Màn Hình Rộng Mở! #HuaweiPuraX #FoldablePhone #HarmonyOSNext #HarmonyIntelligence #Kirin9020 #ThiếtKếĐộtPhá #QueenMobile #MuaSắmThôngMinh #KhuyếnMãiHấpDẫn Mở Ra Tương Lai Với Huawei Pura X - Điện Thoại Gập Ngang Độc Đáo! Huawei Pura X đã chính thức ra mắt, đánh dấu bước tiến đột phá trong thiết kế điện thoại gập. Với khả năng mở ngang, Pura X mang đến trải nghiệm màn hình rộng rãi như một chiếc máy tính bảng mini, cùng hệ điều hành HarmonyOS Next tiên tiến và tích hợp trí tuệ nhân tạo Harmony Intelligence.

Huawei Pura X – Điện thoại gập ngang độc đáo, trải nghiệm rộng mở! 🌿💖

Huawei Pura X - Điện Thoại Gập Ngang Đột Phá, Trải Nghiệm Màn Hình Rộng Mở! #HuaweiPuraX #FoldablePhone #HarmonyOSNext #HarmonyIntelligence #Kirin9020 #ThiếtKếĐộtPhá #QueenMobile #MuaSắmThôngMinh #KhuyếnMãiHấpDẫn Mở Ra Tương Lai…

0 0 0 0
Post image

Huawei Pocket 3: indiscrezioni sul prezzo prima del lancio
#FlipPhone #HarmonyOSNext #Huawei #HuaweiPocket2 #HuaweiPocket3 #HuaweiPura #Kirin9020 #MobileNews #Notizie #Prezzo #Smartphone #Tech #TechNews #Tecnologia
www.ceotech.it/huawei-pocke...

0 0 0 0
Preview
Huawei Pocket 3 May Be Unveiled In China Next Week Huawei chairman Richard Yu has revealed via Weibo that the company plans to unveil a new smartphone by next week.

Huawei Pocket 3 May Be Unveiled In China Next Week #harmonyosnext #huawei #mobilephones #pocket3 #teaser #weibo

0 0 0 0

📱 Huawei Mate 70 Series launched with HarmonyOS NEXT, a break from Android. #HarmonyOSNEXT https://fefd.link/xIKU0

0 0 0 0
Post image

This is very devastating since the death of Windows Phone in 2017 lol
#RIP #duolingoowl #Duolingo #HarmonyOSNext #OpenHarmony

0 0 0 0
Post image

Wuthering Waves coming soon to HarmonyOS Next AppGallery
#HarmonyOSNext #OpenHarmony #AppGallery #WutheringWaves #CH

2 0 0 0
HarmonyOS NEXT Installation DeepSeek for Android Container DroiTong
HarmonyOS NEXT Installation DeepSeek for Android Container DroiTong YouTube video by Living In Harmony

Global HarmonyOS Next Testers on DroiTong DeepSeek
#Tutorials
#HarmonyOSNext #OpenHarmony #DroiTong #Container #DeepSeek #App #Tutorials
www.youtube.com/shorts/Phz0l...

2 0 0 0
Preview
The Appillionare 2025 Challenge: What you want to see on global HarmonyOS Next AppGallery Wish List (NEXTMAX) - HarmonyOSHub This year and going into 2025 new year resolution ahead of global expansion after HarmonyOS 4.2/EMUI 14.2 phone and HarmonyOS 4.x tablet users as well as

The Appillionare 2025 Challenge: What you want to see on global HarmonyOS Next AppGallery Wish List - HarmonyOSHub
#Challenge #Global
#Appillionare #HarmonyOSNext #OpenHarmony #AppGallery #Devs #Apps
harmonyoshub.com/the-appillio...

1 0 1 0