Guide to Developing the First Cangjie and ArkTS Hybrid HarmonyOS Next Application
I. Environment Preparation and Project Creation
To ensure optimal performance, this article is based on DevEco Studio 5.0.2 Release and DevEco Studio-Cangjie Plugin 5.0.7.100 Beta1. Developers can download the latest version through the specified link.
Target Audience: This document is designed for HarmonyOS application developers who have mastered the basics of the Cangjie language, ArkTS language, and UI framework. It helps developers quickly familiarize themselves with the project structure and development process by building a hybrid application with page navigation/return functionality.
Steps to Create a Hybrid Project
- Open DevEco Studio, select File > New > Create Project to create a new project.
- Select the Application development type.
- Choose the [Cangjie] Hybrid Ability template and click Next.
- Keep the default configuration parameters unchanged.
- Click Finish and wait for the project to be created.
Note: For pure Cangjie project development, select the [Cangjie] Empty Ability template. For more information on templates, refer to the project module introduction document.
II. Analysis of Project Directory Structure
The successfully created Cangjie and ArkTS hybrid project has a specific directory structure, and understanding this structure is crucial for subsequent development.
Project_name
├── .hvigor
├── .idea
├── AppScope
│ ├── resources
│ └── app.json5
├── entry
│ ├── build
│ ├── har
│ │ └── CJHyAPIRegister-v1.0.1.har
│ ├── libs
│ ├── oh_modules
│ ├── src
│ │ ├── main
│ │ │ ├── cangjie
│ │ │ │ ├── loader
│ │ │ │ ├── cjpm.toml
│ │ │ │ └── index.cj
│ │ │ ├── ets
│ │ │ │ ├── entryability
│ │ │ │ ├── entrybackupability
│ │ │ │ └── pages
│ │ │ ├── resources
│ │ │ └── module.json5
│ │ ├── mock
│ │ ├── ohosTest
│ │ └── test
│ ├── build-profile.json5
│ ├── hvigorfile.ts
│ ├── obfuscation-rules.txt
│ ├── oh-package.json5
│ └── oh-package-lock.json5
├── hvigor
│ ├── cangjie-build-support-x.y.z.tgz
│ └── hvigor-config.json5
├── oh_modules
├── build-profile.json5
├── code-linter.json5
├── hvigorfile.ts
├── local.properties
├── oh-package.json5
└── oh-package-lock.json5
Key File Descriptions
- AppScope > app.json5: Global configuration information for the application.
- entry: The HarmonyOS project module, which generates a HAP package after compilation.
- src > har: Stores HAR modules dependent on Cangjie and ArkTS interoperation.
- src > main > cangjie: Cangjie source code directory.
- src > main > cangjie > loader: Dependency library for Cangjie and ArkTS interoperation.
- src > main > cangjie > cjpm.toml: Cangjie package management configuration file.
- src > main > ets: ArkTS source code directory.
- src > main > resources: Application resource file directory.
- src > main > module.json5: Module configuration file, including HAP and application configuration information.
III. Building the First Page (Pure ArkTS Page)
This section guides you to create a basic ArkTS page with text and button components.
Creating a Basic Page with Text Components
Open the Index.ets file in the entry > src > main > ets > pages directory and write the following code:
// Index.ets
@Entry
@Component
struct Index {
@State message: string = 'Hello World'
build() {
Row() {
Column() {
Text(this.message)
.fontSize(50)
.fontWeight(FontWeight.Bold)
}
.width('100%')
}
.height('100%')
}
}
This code creates a simple page displaying "Hello World" text in the center.
Adding Button Components for Page Navigation
Add a button component to the existing page:
// Index.ets
@Entry
@Component
struct Index {
@State message: string = 'Hello World'
build() {
Row() {
Column() {
Text(this.message)
.fontSize(50)
.fontWeight(FontWeight.Bold)
// Add button component
Button() {
Text('Next')
.fontSize(30)
.fontWeight(FontWeight.Bold)
}
.type(ButtonType.Capsule)
.margin({
top: 20
})
.backgroundColor('#0D9FFB')
.width('40%')
.height('5%')
}
.width('100%')
}
.height('100%')
}
}
This button will be used to implement page navigation in the next section.
IV. Building the Second Page (ArkTS and Cangjie Hybrid Page)
In a hybrid development scenario, a Cangjie page is embedded as a component in an ArkTS page, requiring specific configuration and encapsulation.
Steps to Create a Hybrid Page
- In the Project window, open entry > src > main.
- Right-click the cangjie folder.
- Select New > Cangjie Page > Empty Page.
- Name it Second.
- Select the With ArkTS Wrapper option.
- Click OK.
After completing the operations, the project directory will be updated as follows:
entry
├── .preview
├── build
├── libs
├── oh_modules
└── src
└── main
├── cangjie
│ ├── loader
│ ├── cjpm.toml
│ └── index.cj
├── ets
│ ├── entryability
│ ├── entrybackupability
│ └── pages
│ ├── Index.ets
│ └── Second.ets
├── resources
└── module.json5
Two key files will be automatically generated:
- second.cj (Cangjie source code) in src > main > cangjie.
- second.ets (ArkTS source code) in src > ets > pages.
Additionally, the system will:
- Generate the CJHybridView-vx.y.z.har package in entry > har.
- Add this HAR package dependency to the dependencies field of entry > oh-package.json5.
Configuring the Cangjie Page Component
Edit the second.cj file and add UI components:
// second.cj
package ohos_app_cangjie_entry
import ohos.base.*
import ohos.component.*
import ohos.hybrid_base.*
import ohos.state_macro_manage.*
import ohos.state_manage.*
import cj_res_entry.app
@HybridComponentEntry
@Component
class Second {
@State var msg: String = "Hello Cangjie"
public func build() {
Row() {
Column() {
Text(this.msg)
.fontSize(50)
.fontWeight(FontWeight.Bold)
Button() {
Text("Back")
.fontSize(30)
.fontWeight(FontWeight.Bold)
}
.shape(ShapeType.Capsule)
.margin(top: 20)
.backgroundColor(Color(0x0D9FFB))
.width(40.percent)
.height(5.percent)
}
.width(100.percent)
}
.height(100.percent)
}
}
Configuring the ArkTS Wrapper Page
The automatically generated second.ets file provides an ArkTS wrapper template:
// second.ets
// Embed Cangjie page in ArkTS page
import { CJHybridComponentV2 } from 'cjhybridview';
import { register_hsp_api } from 'cjhyapiregister';
register_hsp_api()
@Entry
@Component
struct Second {
build() {
Row() {
// Embed Cangjie page via CJHybridComponentV2 interface
CJHybridComponentV2({
library: "ohos_app_cangjie_entry", // Package name of the Cangjie page
component: "Second" // Class name of the Cangjie page
})
}
.height('100%')
.width('100%')
}
}
V. Implementing Navigation Between Pages
This section details how to implement navigation between ArkTS and Cangjie pages.
Navigating from the First Page to the Second Page
Add a click event handler to the button in Index.ets:
// Index.ets
// Import page routing module
import { router } from '@kit.ArkUI';
import { BusinessError } from '@kit.BasicServicesKit';
@Entry
@Component
struct Index {
@State message: string = 'Hello World'
build() {
Row() {
Column() {
Text(this.message)
.fontSize(50)
.fontWeight(FontWeight.Bold)
// Add button to respond to user clicks
Button() {
Text('Next')
.fontSize(30)
.fontWeight(FontWeight.Bold)
}
.type(ButtonType.Capsule)
.margin({
top: 20
})
.backgroundColor('#0D9FFB')
.width('40%')
.height('5%')
// Bind onClick event to the navigation button
.onClick(() => {
console.info(`Succeeded in clicking the 'Next' button.`)
// Navigate to the second page
router.pushUrl({ url: 'pages/second' }).then(() => {
console.info('Succeeded in jumping to the second page.')
}).catch((err: BusinessError) => {
console.error(`Failed to jump to the second page. Code is ${err.code}, message is ${err.message}`)
})
})
}
.width('100%')
}
.height('100%')
}
}
Returning from the Second Page to the First Page
Since the routing systems of Cangjie and ArkTS are not directly interoperable, callbacks must be implemented through an interoperation mechanism.
Registering ArkTS Functions on the Cangjie Side
Edit the index.cj file in entry > src > main > cangjie:
// index.cj
package ohos_app_cangjie_entry
import ohos.base.*
import ohos.ark_interop.*
import ohos.ark_interop_macro.*
import std.collection.*
// Define a global HashMap to store ArkTS-registered functions
public let globalJSFunction = HashMap<String, ()->Unit>()
@Interop[ArkTS]
public func registerJSFunc(name: String, fn: ()->Unit): Unit {
// Check if the function is already registered
if (globalJSFunction.contains(name)) {
AppLog.error("registerJSFunc failed(err: func ${name} already exists)")
return
}
// Save the function reference
globalJSFunction.put(name, fn)
}
@Interop[ArkTS]
public func unregisterJSFunc(name: String): Unit {
globalJSFunction.remove(name)
}
To generate the interoperation interface file, right-click in the index.cj editing window and select Generate... > Cangjie-ArkTS Interop API. The auto-generated interface declaration is in entry > src > main > cangjie > ark_interop_api > ark_interop_api.d.ts.
Registering Routing Functions on the ArkTS Side
Edit second.ets and add function registration logic:
// second.ets
import { CJHybridComponentV2 } from 'cjhybridview';
import { register_hsp_api } from 'cjhyapiregister';
// Import page routing module
import { router } from '@kit.ArkUI';
import { BusinessError } from '@kit.BasicServicesKit';
// Import Cangjie-ArkTS interoperation library
import { requireCJLib } from 'libark_interop_loader.so';
// Import auto-generated interoperation interface
import { CustomLib } from 'libark_interop_api.so';
register_hsp_api()
// Load the Cangjie so library containing registerJSFunc
let cjlib = requireCJLib("libohos_app_cangjie_entry.so") as CustomLib
@Entry
@Component
struct Second {
aboutToAppear(): void {
// Register callback before page appears
cjlib.registerJSFunc('SecondPageRouterBack', () => {
try {
// Perform return operation
router.back()
console.info('Succeeded in returning to the first page.')
} catch (err) {
let code = (err as BusinessError).code;
let message = (err as BusinessError).message;
console.error(`Failed to return to the first page. Code is ${code}, message is ${message}`)
}
})
}
aboutToDisappear(): void {
// Unregister callback before page is destroyed
cjlib.unregisterJSFunc('SecondPageRouterBack')
}
build() {
Row() {
// Embed Cangjie page component
CJHybridComponentV2({
library: "ohos_app_cangjie_entry",
component: "Second"
})
}
.height('100%')
.width('100%')
}
}
Calling ArkTS Functions on the Cangjie Side
Edit second.cj and add event handling for the return button:
// second.cj
package ohos_app_cangjie_entry
import ohos.base.*
import ohos.component.*
import ohos.hybrid_base.*
import ohos.state_macro_manage.*
import ohos.state_manage.*
import cj_res_entry.app
@HybridComponentEntry
@Component
class Second {
@State var msg: String = "Hello Cangjie"
public func build() {
Row() {
Column() {
Text(this.msg)
.fontSize(50)
.fontWeight(FontWeight.Bold)
Button() {
Text("Back")
.fontSize(30)
.fontWeight(FontWeight.Bold)
}
.shape(ShapeType.Capsule)
.margin(top: 20)
.backgroundColor(Color(0x0D9FFB))
.width(40.percent)
.height(5.percent)
// Bind click event to the return button
.onClick {
AppLog.info("Succeeded in clicking the 'Back' button.")
let optFn = globalJSFunction.get("SecondPageRouterBack")
if (let Some(fn) <- optFn) {
fn() // Call the callback registered by ArkTS
} else {
AppLog.error("Failed to return to the first page. Callback not exists")
}
}
}
.width(100.percent)
}
.height(100.percent)
}
}
VI. Running and Testing the Application
After completing development, test the application on a real device or simulator.
Running on a Local Real Device
- Connect a HarmonyOS device to the computer via USB.
- In DevEco Studio, go to File > Project Structure... > Project > SigningConfigs.
- Check Support HarmonyOS and Automatically generate signature.
- Click Sign In and log in with a Huawei account.
- Wait for automatic signing to complete, then click OK.
- Click the run button in the upper-right toolbar of the editing window.
Running on a Simulator
- Create a Phone-type simulator device.
- Select the simulator in the DevEco Studio device list.
- Note: The default compilation architecture for Cangjie projects is arm64-v8a.
- For x86 simulators (Windows/x86_64 or MacOS/x86_64), add x86_64 support in entry > build-profile.json5:
"buildOption": {
"cangjieOptions": {
"path": "./src/main/cangjie/cjpm.toml",
"abiFilters": ["arm64-v8a", "x86_64"]
}
}
- Click the run button to test.
VII. Summary and Extensions
Congratulations on completing the development of your first Cangjie and ArkTS hybrid application! Through this tutorial, you have mastered
Top comments (0)