【仓颉开发实战】基于 OpenHarmony 实现拨打电话功能
本文将以仓颉语言 为开发载体,基于 OpenHarmony 的 Stage 模型,通过kit.TelephonyKit电信服务模块实现简易的拨打电话功能 ------ 支持手动输入电话号码,点击按钮后跳转到系统拨号界面并填充待拨打号码,同时增加设备呼叫能力校验,适配不同设备的功能支持情况。
功能介绍
本示例为基础的电信能力调用案例,核心实现 2 个关键功能:
- 提供文本输入框,支持手动输入电话号码并实时绑定页面状态;
- 点击「拨打电话」按钮后,先校验设备是否支持语音呼叫能力,支持则跳转到系统拨号界面并填充号码,不支持则弹出吐司提示。
效果

开发环境准备
开发前需搭建符合要求的仓颉开发环境,确保工具与版本匹配,避免编译运行异常:
- 开发工具:DevEco Studio 6.0.2 Release 及以上版本;
- SDK 版本:OpenHarmony API22 及以上(仓颉语言核心支持版本);
- 运行设备:OpenHarmony 标准系统设备(如 Mate60 系列);
- 开发模型:Stage 模型(OpenHarmony 主流开发模型)。
工程目录与文件说明
本示例工程结构极简,核心代码均在entry/src/main/cangjie/目录下,共 3 个仓颉文件,各司其职且耦合度低,以下为目录结构及核心文件作用说明:
entry/src/main/cangjie/
|---ability_stage.cj // 应用能力阶段入口,初始化应用全局生命周期
|---main_ability.cj // 主界面UI布局+核心业务逻辑(输入、拨号、能力校验)
|---index.cj // 主UIAbility实现,管理页面生命周期、封装全局上下文
核心实现步骤
以下按文件维度 展示完整可运行代码,并对关键逻辑、核心 API、代码设计思路进行详细解析,代码中补充了规范注释,便于理解。
1. 应用能力阶段入口:ability_stage.cj
作为应用的全局生命周期入口 ,继承AbilityStage并实现onCreate方法,用于应用启动时的初始化操作(如日志打印、全局配置初始化),本示例仅做基础的启动日志输出。
package ohos_app_cangjie_entry
import kit.AbilityKit.AbilityStage
import kit.PerformanceAnalysisKit.Hilog
class MyAbilityStage <: AbilityStage {
public override func onCreate(): Unit {
Hilog.info(1, "Cangjie", "MyAbilityStage onCreated.")
}
}
2. 主 UIAbility 与全局上下文:index.cj
核心实现MainAbility(主界面的 UIAbility),管理页面的生命周期、窗口舞台加载,同时封装全局可访问的 UIAbilityContext 和 WindowStage ------ 因为TelephonyKit的拨打电话 API 需要UIAbilityContext作为入参,通过全局类封装可实现跨文件的上下文调用,避免参数层层传递。
package ohos_app_cangjie_entry
import kit.ArkUI.LengthProp
import kit.ArkUI.Column
import kit.ArkUI.Row
import kit.ArkUI.Text
import kit.ArkUI.CustomView
import kit.ArkUI.CJEntry
import kit.ArkUI.loadNativeView
import kit.ArkUI.FontWeight
import kit.ArkUI.SubscriberManager
import kit.ArkUI.ObservedProperty
import kit.ArkUI.LocalStorage
import ohos.arkui.state_macro_manage.Entry
import ohos.arkui.state_macro_manage.Component
import ohos.arkui.state_macro_manage.State
import kit.TelephonyKit.*
import ohos.arkui.component.text_area.TextArea
import kit.ArkUI.ShowToastOptions
import ohos.base.Color
@Entry
@Component
class EntryView {
@State
var phoneNumber: String = ""
func build() {
Row {
Column {
TextArea(text: "请输入电话号码")
.id("phoneNumberInput")
.margin(6)
.width(60.percent)
.onChange({
value: String => this.phoneNumber = value
})
Text("拨打电话")
.fontSize(30)
.fontWeight(FontWeight.Bold)
.fontColor(Color.Blue)
.onClick(
{
evt =>
let isSupport = Call.hasVoiceCapability()
if (isSupport) {
// 如果设备支持呼叫能力,则继续跳转到拨号界面,并显示拨号的号码
Call.makeCall(Global.abilityContext, phoneNumber)
} else {
getUIContext()
.getPromptAction()
.showToast(ShowToastOptions(message: "该设备不支持呼叫能力"))
}
}
)
}.width(100.percent)
}.height(100.percent)
}
}
关键解析:
Option<>可选类型:仓颉语言的空安全特性,避免空指针异常,Some()表示有值,None表示无值;registerSelf():仓颉中 UIAbility 必须在构造方法中注册自身,否则无法被系统识别;windowStage.loadContent("EntryView"):加载main_ability.cj中定义的@Entry标记的根组件,作为页面展示内容;- 全局类
Global的只读属性设计:对外仅提供获取方法,不允许直接修改,保证上下文的唯一性和安全性。
3. 主界面与拨号核心逻辑:main_ability.cj
本示例的核心业务文件 ,实现了「电话号码输入框 + 拨打电话按钮」的 UI 布局,同时绑定页面状态、实现设备呼叫能力校验 、拨打电话 API 调用 、异常提示等核心逻辑,所有用户交互均在此实现。
package ohos_app_cangjie_entry
import kit.PerformanceAnalysisKit.Hilog
import kit.AbilityKit.Want
import kit.AbilityKit.UIAbility
import kit.AbilityKit.LaunchParam
import kit.AbilityKit.LaunchReason
import kit.ArkUI.WindowStage
import kit.AbilityKit.UIAbilityContext
class MainAbility <: UIAbility {
public init() {
super()
registerSelf()
}
public override func onCreate(want: Want, launchParam: LaunchParam): Unit {
Hilog.info(1, "Cangjie", "MainAbility OnCreated.${want.abilityName}")
match (launchParam.launchReason) {
case LaunchReason.StartAbility => Hilog.info(1, "Cangjie", "START_ABILITY")
case _ => ()
}
}
public override func onWindowStageCreate(windowStage: WindowStage): Unit {
Hilog.info(1, "Cangjie", "MainAbility onWindowStageCreate.")
Global._abilityContext = Some(this.context)
Global._windowStage = Some(windowStage)
windowStage.loadContent("EntryView")
}
}
public class Global {
public static var _abilityContext: Option<UIAbilityContext> = None
public static var _windowStage: Option<WindowStage> = None
public static prop abilityContext: UIAbilityContext {
get() {
match (_abilityContext) {
case Some(context) => context
case None => throw Exception("Global.abilityContext is not set")
}
}
}
public static prop windowStage: WindowStage {
get() {
match (_windowStage) {
case Some(stage) => stage
case None => throw Exception("Global.windowStage is not set")
}
}
}
}
约束与限制
- 本示例仅支持标准系统上运行,支持设备:mate60;
- 本示例为Stage模型,支持API22及以上版本的SDK;
- 本示例调用
Call.makeCall()仅实现跳转到系统原生拨号界面并填充号码,并未直接发起通话,实际拨号操作由用户在系统界面手动完成,属于系统能力的间接调用 - 本示例需要使用DevEco Studio 6.0.2 Release才可编译运行。
案例出处:https://atomgit.com/openharmony-sig/applications_app_samples_cangjie