【HarmonyOS之旅】基于ArkTS开发(一) -> Ability开发一

news2025/1/7 7:24:50

目录

1 -> FA模型综述

1.1 -> 整体架构

1.2 -> 应用包结构

1.3 -> 生命周期

1.4 -> 进程线程模型

2 -> PageAbility开发

2.1 -> 概述

2.1.1 ->功能简介

2.1.2 -> PageAbility的生命周期

2.1.3 -> 启动模式

2.2 -> featureAbility接口说明

2.3 -> 启动本地PageAbility

2.4 -> 生命周期接口说明

3 -> ServiceAbility开发

3.1 -> 场景介绍

3.2 -> 接口说明

3.3 -> 开发步骤

3.3.1 -> 创建Service

3.3.2 -> 启动Service

3.3.3 -> 停止Service

3.3.4 -> 连接本地Service


1 -> FA模型综述

1.1 -> 整体架构

HarmonyOS用户程序的开发本质上就是开发Ability。HarmonyOS系统是通过对Ability调度,结合系统提供的一致性调度契约对Ability进行生命周期管理,从而实现对用户程序的调度。

Ability框架在API 8及更早版本使用FA模型。FA模型中Ability分为PageAbility、ServiceAbility、DataAbility、FormAbility几种类型。其中:

  • PageAbility是具备ArkUI实现的Ability,是用户具体可见并可以交互的Ability实例。
  • ServiceAbility也是Ability一种,但是没有UI,提供其他Ability调用自定义的服务,在后台运行。
  • DataAbility也是没有UI的Ability,提供其他Ability进行数据的增删查服务,在后台运行。
  • FormAbility是卡片Ability,是一种界面展示形式。

1.2 -> 应用包结构

1.3 -> 生命周期

在所有Ability中,PageAbility因为具有界面,也是应用的交互入口,因此生命周期更加复杂。

PageAbility生命周期回调如下图所示:

其他类型Ability的生命周期可参考PageAbility生命周期去除前后台切换以及onShow的部分进行理解。可以在 app.js/app.ets 中重写生命周期函数,在对应的生命周期函数内处理应用相应逻辑。目前app.js环境中仅支持onCreate和onDestroy回调,app.ets环境支持全量生命周期回调。

1.4 -> 进程线程模型

应用独享独立进程,Ability独享独立线程,应用进程在Ability第一次启动时创建,并为启动的Ability创建线程,应用启动后再启动应用内其他Ability,会为每一个Ability创建相应的线程。每个Ability绑定一个独立的JSRuntime实例,因此Ability之间是隔离的。

2 -> PageAbility开发

2.1 -> 概述

2.1.1 ->功能简介

PageAbility是具备ArkUI实现的Ability,是开发者具体可见并可以交互的Ability实例。开发者通过IDE创建Ability时,IDE会自动创建相关模板代码。PageAbility相关能力通过单独的featureAbility实现,生命周期相关回调则通过app.js/app.ets中各个回调函数实现。

2.1.2 -> PageAbility的生命周期

PageAbility生命周期介绍(Ability Life Cycle):

PageAbility生命周期是PageAbility被调度到INACTIVE、ACTIVE、BACKGROUND等各个状态的统称。

Ability生命周期状态说明:

  • UNINITIALIZED:未初始状态,为临时状态,PageAbility被创建后会由UNINITIALIZED状态进入INITIAL状态。

  • INITIAL:初始化状态,也表示停止状态,表示当前PageAbility未运行,PageAbility被启动后由INITIAL态进入ACTIVE状态。

  • INACTIVE:失去焦点状态,表示当前窗口已显示但是无焦点状态。

  • ACTIVE:前台激活状态,表示当前窗口已显示,并获取焦点。

  • BACKGROUND:后台状态,表示当前PageAbility退到后台,PageAbility在被销毁后由BACKGROUND状态进入INITIAL状态,或者重新被激活后由BACKGROUND状态进入ACTIVE状态。

PageAbility提供生命周期回调,开发者可以在app.js/app.ets中重写生命周期相关回调函数 。目前app.js环境中仅支持onCreate和onDestroy回调,app.ets环境支持全量生命周期回调。

2.1.3 -> 启动模式

ability支持单实例和多实例两种启动模式。

在config.json中通过launchType配置项,可以配置具体的启动模式。

启动模式描述说明
standard多实例每次startAbility都会启动一个新的实例
singleton单实例系统中只存在唯一一个实例,startAbility时,如果已存在,则复用系统中的唯一一个实例

缺省情况下是singleton模式。

2.2 -> featureAbility接口说明

表1 featureAbility接口介绍
接口名描述
void startAbility(parameter: StartAbilityParameter)启动Ability
Context getContext():获取应用Context
void terminateSelf()结束Ability
bool hasWindowFocus()是否获取焦点

2.3 -> 启动本地PageAbility

导入模块

  import featureAbility from '@ohos.ability.featureAbility'

示例

import featureAbility from '@ohos.ability.featureAbility'
featureAbility.startAbility({
    want:
    {
        action: "",
        entities: [""],
        type: "",
        options: {
            // Grant the permission to perform read operations on the URI.
            authReadUriPermission: true,
            // Grant the permission to perform write operations on the URI.
            authWriteUriPermission: true,
            // support forwarding the Want result to the ability.
            abilityForwardResult: true,
            // Enable ability continuation.
            abilityContinuation: true,
            // Specify that a component does not belong to ohos.
            notOhosComponent: true,
            // Specify that an ability is started.
            abilityFormEnabled: true,
            // Grant the permission for possible persisting on the URI.
            authPersistableUriPermission: true,
            // Grant the permission for possible persisting on the prefix URI.
            authPrefixUriPermission: true,
            // Support distributed scheduling system startup on multiple devices.
            abilitySliceMultiDevice: true,
            // A service ability is started regardless of whether the host application has been started.
            startForegroundAbility: true,
            // Install the specified ability if it is not installed.
            installOnDemand: true,
            // Return the result to the ability slice.
            abilitySliceForwardResult: true,
            // Install the specified ability with background mode if it is not installed.
            installWithBackgroundMode: true
        },
        deviceId: "",
        bundleName: "com.example.startability",
        abilityName: "com.example.startability.MainAbility",
        uri: ""
    },
});

want参数也可以使用parameters参数,使用key-value的方式输入。

示例

import featureAbility from '@ohos.ability.featureAbility'
featureAbility.startAbility({
    want:
    {
        bundleName: "com.example.startability",
        uri: "",
        parameters: {
            abilityName: "com.example.startability.MainAbility"
        }
    },
});

2.4 -> 生命周期接口说明

表2 生命周期回调函数介绍
接口名描述
onShow()Ability由后台不可见状态切换到前台可见状态调用onShow方法,此时用户在屏幕可以看到该Ability。
onHide()Ability由前台切换到后台不可见状态时调用onHide方法,此时用户在屏幕看不到该Ability。
onDestroy()应用退出,销毁Ability对象前调用onDestroy方法,开发者可以在该方法里做一些回收资源、清空缓存等应用退出前的准备工作。
onCreate()Ability第一次启动创建Ability时调用onCreate方法,开发者可以在该方法里做一些应用初始化工作。
onInactive()Ability失去焦点时调用onInactive方法,Ability在进入后台状态时会先失去焦点,再进入后台。
onActive()Ability切换到前台,并且已经获取焦点时调用onActive方法。

示例

开需要重写app.js/app.ets中相关生命周期回调函数,IDE模板默认生成onCreate()和onDestroy()方法,其他方法需要自行实现。

export default {
  onCreate() {
    console.info('Application onCreate')
  },
  onDestroy() {
    console.info('Application onDestroy')
  },
  onShow(){
    console.info('Application onShow')
  },
  onHide(){
    console.info('Application onHide')
  },
  onInactive(){
    console.info('Application onInactive')
  },
  onActive(){
    console.info('Application onActive')
  },
}

3 -> ServiceAbility开发

3.1 -> 场景介绍

基于Service模板的Ability主要用于后台运行任务(如执行音乐播放、文件下载等),但不提供用户交互界面。Service可由其他应用或Ability启动,即使用户切换到其他应用,Service仍将在后台继续运行。

3.2 -> 接口说明

表3 Service中相关生命周期功能介绍
接口名描述
onStart该方法在创建Service的时候调用,用于Service的初始化。在Service的整个生命周期只会调用一次,调用时传入的Want应为空。
onCommand在Service创建完成之后调用,该方法在客户端每次启动该Service时都会调用,开发者可以在该方法中做一些调用统计、初始化类的操作。
onConnect在Ability和Service连接时调用。
onDisconnect在Ability与绑定的Service断开连接时调用。
onStop在Service销毁时调用。Service应通过实现此方法来清理任何资源,如关闭线程、注册的侦听器等。

3.3 -> 开发步骤

3.3.1 -> 创建Service

1. Service也是一种Ability,Ability为Service提供了以下生命周期方法,开发者可以重写这些方法,来添加其他Ability请求与Service Ability交互时的处理方法。

创建Service的代码示例如下:

export default {
    onStart() {
        console.log('ServiceAbility onStart');
    },
    onCommand(want, startId) {
        console.log('ServiceAbility onCommand');
    },
    onConnect(want) {
        console.log('ServiceAbility OnConnect');
        return new FirstServiceAbilityStub('test');
    },
    onDisconnect(want) {
        console.log('ServiceAbility OnDisConnect');
    },
    onStop() {
        console.log('ServiceAbility onStop');
    },
}

2. 注册Service。

Service也需要在应用配置文件config.json中进行注册,注册类型type需要设置为service。

 {
     "module": {
         "abilities": [         
             {    
                 "name": ".ServiceAbility",
                 "type": "service",
                 "visible": true
                 ...
             }
         ]
         ...
     }
     ...
 }

3.3.2 -> 启动Service

Ability为开发者提供了startAbility()方法来启动另外一个Ability。因为Service也是Ability的一种,开发者同样可以通过将Want传递给该方法来启动Service。

开发者可以通过构造包含bundleName与abilityName的Want对象来设置目标Service信息。参数的含义如下:

  • bundleName:表示包名称。
  • abilityName:表示待启动的Ability名称。
import featureAbility from '@ohos.ability.featureAbility';
let promise = featureAbility.startAbility(
    {
        want:
        {
            bundleName: "com.jstest.service",
            abilityName: "com.jstest.service.ServiceAbility",
        },
    }
); 

执行上述代码后,Ability将通过startAbility() 方法来启动Service。

  • 如果Service尚未运行,则系统会先调用onStart()来初始化Service,再回调Service的onCommand()方法来启动Service。
  • 如果Service正在运行,则系统会直接回调Service的onCommand()方法来启动Service。

3.3.3 -> 停止Service

Service一旦创建就会一直保持在后台运行,除非必须回收内存资源,否则系统不会停止或销毁Service。开发者可以在Service中通过terminateSelf()停止本Service。

3.3.4 -> 连接本地Service

如果Service需要与Page Ability或其他应用的Service Ability进行交互,则须创建用于连接的Connection。Service支持其他Ability通过connectAbility()方法与其进行连接。

在使用connectAbility()处理回调时,需要传入目标Service的Want与IAbilityConnection的实例。IAbilityConnection提供了以下方法供开发者实现:onConnect()是用来处理连接Service成功的回调,onDisconnect()是用来处理Service异常死亡的回调,onFailed()是用来处理连接Service失败的回调。

import prompt from '@system.prompt'

var option = {
    onConnect: function onConnectCallback(element, proxy) {
        console.log(`onConnectLocalService onConnectDone`)
        if (proxy === null) {
            prompt.showToast({
                message: "Connect service failed"
            })
            return
        }
        let data = rpc.MessageParcel.create()
        let reply = rpc.MessageParcel.create()
        let option = new rpc.MessageOption()
        data.writeInterfaceToken("connect.test.token")
        proxy.sendRequest(0, data, reply, option)
        prompt.showToast({
            message: "Connect service success"
        })
    },
    onDisconnect: function onDisconnectCallback(element) {
        console.log(`onConnectLocalService onDisconnectDone element:${element}`)
        prompt.showToast({
            message: "Disconnect service success"
        })
    },
    onFailed: function onFailedCallback(code) {
        console.log(`onConnectLocalService onFailed errCode:${code}`)
        prompt.showToast({
            message: "Connect local service onFailed"
        })
    }
}

连接本地Service的代码示例如下:

import featureAbility from '@ohos.ability.featureAbility';
let connId = featureAbility.connectAbility(
    {
        bundleName: "com.jstest.service",
        abilityName: "com.jstest.service.ServiceAbility",
    },
    {
        onConnect: onConnectCallback,
        onDisconnect: onDisconnectCallback,
        onFailed: onFailedCallback,
    },
);

同时,Service侧也需要在onConnect()时返回IRemoteObject,从而定义与Service进行通信的接口。onConnect()需要返回一个IRemoteObject对象,HarmonyOS提供了IRemoteObject的默认实现,用户可以通过继承rpc.RemoteObject来创建自定义的实现类。

Service侧把自身的实例返回给调用侧的代码示例如下:

import rpc from "@ohos.rpc";

class FirstServiceAbilityStub extends rpc.RemoteObject {
constructor(des: any) {
    if (typeof des === 'string') {
        super(des)
    } else {
        return
    }
}

onRemoteRequest(code: number, data: any, reply: any, option: any) {
    console.log(printLog + ` onRemoteRequest called`)
    if (code === 1) {
        let string = data.readString()
        console.log(printLog + ` string=${string}`)
        let result = Array.from(string).sort().join('')
        console.log(printLog + ` result=${result}`)
        reply.writeString(result)
    } else {
        console.log(printLog + ` unknown request code`)
    }
    return true;
}

感谢各位大佬支持!!!

互三啦!!!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2271943.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

BART:用于自然语言生成、翻译和理解的去噪序列到序列预训练

摘要: 我们提出了BART,一种用于预训练序列到序列模型的去噪自编码器。BART通过以下方式训练:(1) 使用任意的噪声函数对文本进行破坏,(2) 学习一个模型来重建原始文本。它采用了一种标准的基于Transformer的神经机器翻译架构&#…

Promise编码小挑战

题目 我们将实现一个 createImage 函数,该函数返回一个 Promise,用于处理图片加载的异步操作。此外,还会实现暂停执行的 wait 函数。 Part 1: createImage 函数 该函数会: 创建一个新的图片元素。将图片的 src 设置为提供的路径…

Dubbo扩展点加载机制

加载机制中已经存在的一些关键注解,如SPI、©Adaptive> ©Activateo然后介绍整个加载机制中最核心的ExtensionLoader的工作流程及实现原理。最后介绍扩展中使用的类动态编译的实 现原理。 Java SPI Java 5 中的服务提供商https://docs.oracle.com/jav…

【Web】软件系统安全赛CachedVisitor——记一次二开工具的经历

明天开始考试周,百无聊赖开了一把CTF,还顺带体验了下二开工具,让无聊的Z3很开心🙂 CachedVisitor这题 大概描述一下:从main.lua加载一段visit.script中被##LUA_START##(.-)##LUA_END##包裹的lua代码 main.lua loca…

在不到 5 分钟的时间内将威胁情报 PDF 添加为 AI 助手的自定义知识

作者:来自 Elastic jamesspi 安全运营团队通常会维护威胁情报报告的存储库,这些报告包含由报告提供商生成的大量知识。然而,挑战在于,这些报告的内容通常以 PDF 格式存在,使得在处理安全事件或调查时难以检索和引用相关…

vscode代码AI插件Continue 安装与使用

“Continue” 是一款强大的插件,它主要用于在开发过程中提供智能的代码延续功能。例如,当你在编写代码并且需要进行下一步操作或者完成一个代码块时,它能够根据代码的上下文、语法规则以及相关的库和框架知识,为你提供可能的代码续…

leetcode(hot100)4

解题思路:双指针思想 利用两个for循环,第一个for循环把所有非0的全部移到前面,第二个for循环将指针放在非0的末尾全部加上0。 还有一种解法就是利用while循环双指针条件,当不为0就两个指针一起移动 ,为0就只移动右指针…

vulnhub——Earth靶机

使用命令在kali查看靶机ip arp-scan -l 第一 信息收集 使用 nmap 进行 dns 解析 把这两条解析添加到hosts文件中去,这样我们才可以访问页面 这样网站就可以正常打开 扫描ip时候我们发现443是打开的,扫描第二个dns解析的443端口能扫描出来一个 txt 文件…

k8s基础(1)—Kubernetes-Pod

一、Pod简介 Pod是Kubernetes(k8s)系统中可以创建和管理的最小单元,是资源对象模型中由用户创建或部署的最小资源对象模型‌。Pod是由一个或多个容器组成的,这些容器共享存储和网络资源,可以看作是一个逻辑的主机‌。…

【FlutterDart】页面切换 PageView PageController(9 /100)

上效果: 有些不能理解官方例子里的动画为什么没有效果,有可能是我写法不对 后续如果有动画效果修复了,再更新这篇,没有动画效果,总觉得感受的丝滑效果差了很多 上代码: import package:flutter/material.…

使用 NestJS 构建高效且模块化的 Node.js 应用程序,从安装到第一个 API 端点:一步一步指南

一、安装 NestJS 要开始构建一个基于 NestJS 的应用,首先需要安装一系列依赖包。以下是必要的安装命令: npm i --save nestjs/core nestjs/common rxjs reflect-metadata nestjs/platform-express npm install -g ts-node包名介绍nestjs/coreNestJS 框…

第07章 存储管理(一)

一、磁盘简介 1.1 名称称呼 磁盘/硬盘/disk是同一个东西,不同于内存的是容量比较大。 1.2 类型 机械:机械硬盘即是传统普通硬盘,主要由:盘片,磁头,盘片转轴及控制电机,磁头控制器&#xff0…

Appium(一)--- 环境搭建

一、Android自动化环境搭建 1、JDK 必须1.8及以上(1) 安装:默认安装(2) 环境变量配置新建JAVA_HOME:安装路径新建CLASSPath%JAVA_HOME%\lib\dt.jar;%JAVA_HOME%\lib\tools.jar在path中增加:%JAVA_HOME%\bin;%JAVA_HOME%\jre\bin;(3) 验证…

Framebuffer 驱动

实验环境: 正点原子alpha 开发板 调试自己编写的framebuffer 驱动,加载到内核之后,显示出小企鹅 1. Framebufer 总体框架 fbmem.c 作为Framebuffer的核心层,向上提供app使用的接口,向下屏蔽了底层各种硬件的差异; 准确来说fbmem.c 就是一个字符设备驱动框架的程序,对…

复变函数复习

复数 复数的方根计算 例题: 复变函数 导数 解析函数 调和函数 例题: V是U的共轭调和函数 但U不是V的共轭调和函数 其中U和V满足柯西黎曼方程 经典例题 求解析函数例题: 初等函数 指数函数 对数函数 幂函数 三角函数 级数 极限 收敛半…

在DJI无人机上运行VINS-FUISON(PSDK 转 ROS)

安装ceres出现以下报错,将2版本的ceres换成1版本的ceres CMake did not find one.Could not find a package configuration file provided by "absl" with any ofthe following names:abslConfig.cmakeabsl-config.cmakeAdd the installation prefix of …

HTML5实现好看的博客网站、通用大作业网页模板源码

HTML5实现好看的博客网站、通用大作业网页模板源码 前言一、设计来源1.1 主界面1.2 列表界面1.3 文章界面 二、效果和源码2.1 动态效果2.2 源代码 源码下载结束语 HTML5实现好看的博客网站、通用大作业网页模板源码,博客网站源码,HTML模板源码&#xff0…

线性回归从0到1实践

导入需要的包 from idlelib.configdialog import tracers %matplotlib inline import random import torch from d2l import torch as d2l根据有噪声的线性模型构造一个人造数据集。我们使用线性模型参数 w [ 2 , − 3 , 4 ] T w [2,-3,4]^T w[2,−3,4]T、b4.2 和噪声 ϵ \…

从摩托罗拉手机打印短信的简单方法

昨天我试图从摩托罗拉智能手机上打印短信,但当我通过USB将手机连接到电脑时,我在电脑上找不到它们。由于我的手机内存已达到限制,并且我想保留短信的纸质版本,您能帮我将短信从摩托罗拉手机导出到计算机吗? 如您所知&…

elementui table 表格 分页多选,保持选中状态

elementui多选时分页,解决选中状态无法保留选中项问题: 在el-table标签中加入row-key,row-key的值取当前数据里的唯一key在el-table-column selection 项中加入以下:reserve-selection“true” 完成后,将需要清空的地方 ( 如返回…