ToB企服应用市场:ToB评测及商务社交产业平台
标题:
鸿蒙计划分析(一)-AbilityKit
[打印本页]
作者:
大号在练葵花宝典
时间:
2024-12-11 03:27
标题:
鸿蒙计划分析(一)-AbilityKit
综述
本篇主要是联合官方文档和项目对基础架构进行分析,针对AbilityKit进行现实项目的分析。
Api9以后使用stage模型开辟。
应用步伐包
类型
包括:HAP属于可独立运行的应用Module(一个应用可以包罗多个HAP),HAR和HSP,属于Libary,HAR是静态Library(资源拷贝),HSP是共享Library(共享资源)。
HAP
HAP是Ability类型的Module, 实现应用的功能和特性。
每一个Ability类型的Module编译后,会天生一个以.hap为后缀的文件。
HAP包可以独立安装和运行,是应用安装的根本单位,一个应用中可以包罗一个或多个HAP包。
细分为2种类型:
entry类型的Module:应用的主模块,包罗应用的入口界面、入口图标和主功能特性,编译后天生entry类型的HAP。每一个应用分发到同一类型的装备上的应用步伐包,只能包罗唯逐一个entry类型的HAP。
feature类型的Module:应用的动态特性模块,编译后天生feature类型的HAP。一个应用中可以包罗一个或多个feature类型的HAP,也可以不包罗。
HAR/HSP
两者都是Library类型的Module ,实当代码和资源的共享。同一个Library类型的Module可以被其他的Module多次引用。分为Static和Shared两种类型,编译后会天生共享包。
Static Library:静态共享库。编译后会天生一个以.har为后缀的文件,即静态共享包HAR(Harmony Archive)。
Shared Library:动态共享库。编译后会天生一个以.hsp为后缀的文件,即动态共享包HSP(Harmony Shared Package)
具体可参考步伐设置相干包的创建,库应用及动态引用
包目次结构
设置文件
包括应用级设置信息、以及Module级设置信息:
AppScope > app.json5
:
app.json5设置文件,用于声明应用的全局设置信息,比如应用Bundle名称、应用名称、应用图标、应用版本号等。
具体可以参考app.json5详细设置
entry(Module_name) > src > main > module.json5
:module.json5设置文件,用于声明Module根本信息、支持的装备类型、所含的组件信息、运行所需申请的权限等。
具体可参考module.json5详细设置
ArTs源文件
Module_name > src > main > ets
:
用于存放Module的ArkTS源码文件(.ets文件)。
资源文件
包括应用级资源文件、以及Module级资源文件,支持图形、多媒体、字符串、布局文件等,详见资源分类与访问。
AppScope > resources
:
用于存放应用需要用到的资源文件。
entry(Module_name) > src > main > resources
:
用于存放该Module需要用到的资源文件。
其他设置文件
用于编译构建,包括构建设置文件、编译构建使命脚本、混淆规则文件、依赖的共享包信息等。
build-profile.json5
:
工程级或Module级的构建设置文件,包括应用署名、产品设置等。
hvigorfile.ts
:
应用级或Module级的编译构建使命脚本,开辟者可以自界说编译构建工具版本、控制构建行为的设置参数。
obfuscation-rules.txt
:
混淆规则文件。混淆开启后,在使用Release模式进行编译时,会对代码进行编译、混淆及压缩处理,保护代码资产。
oh-package.json5
:
用于存放依赖库的信息,包括所依赖的三方库和共享包
应用包的开辟
具体可参考https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/application-package-dev-V5
包括各种包的创建方式及动态加载和延迟加载
AbilityKit
这个是Stage开辟模式的最基础模型
应用组件设置
UIAbility划分原则与发起:
UIAbility组件是体系调度的根本单位,为应用提供绘制界面的窗口。一个应用可以包罗一个或多个UIAbility组件。比方,在支付应用中,可以将入口功能和收付款功能分别设置为独立的UIAbility。
每一个UIAbility组件实例都会在最近使命列表中显示一个对应的使命。对于开辟者而言,可以根据具体场景选择单个照旧多个UIAbility,划分发起如下:假如开辟者希望在使命视图中看到一个使命,则发起使用一个UIAbility,多个页面的方式。假如开辟者希望在使命视图中看到多个使命,或者需要同时开启多个窗口,则发起使用多个UIAbility开辟差别的模块功能。
module.json5声明相干设置
UIAbility组件
声明设置
UIAbility对应的是 module.json5的abilities级别的设置
{
"module": {
...
"abilities": [
{
"launchType": "singleton",
...
}
]
}
}
复制代码
生命周期
import { AbilityConstant, UIAbility, Want } from '@kit.AbilityKit';
export default class EntryAbility extends UIAbility {
onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
// 页面初始化
}
// ...
}
复制代码
由于UIAbility持有windowStage因而windowStage的状态变革会回调UIAbility
import { UIAbility } from '@kit.AbilityKit';
import { window } from '@kit.ArkUI';
import { hilog } from '@kit.PerformanceAnalysisKit';
const TAG: string = '[EntryAbility]';
const DOMAIN_NUMBER: number = 0xFF00;
export default class EntryAbility extends UIAbility {
// ...
onWindowStageCreate(windowStage: window.WindowStage): void {
// 设置WindowStage的事件订阅(获焦/失焦、可见/不可见)
try {
windowStage.on('windowStageEvent', (data) => {
let stageEventType: window.WindowStageEventType = data;
switch (stageEventType) {
case window.WindowStageEventType.SHOWN: // 切到前台
hilog.info(DOMAIN_NUMBER, TAG, 'windowStage foreground.');
break;
case window.WindowStageEventType.ACTIVE: // 获焦状态
hilog.info(DOMAIN_NUMBER, TAG, 'windowStage active.');
break;
case window.WindowStageEventType.INACTIVE: // 失焦状态
hilog.info(DOMAIN_NUMBER, TAG, 'windowStage inactive.');
break;
case window.WindowStageEventType.HIDDEN: // 切到后台
hilog.info(DOMAIN_NUMBER, TAG, 'windowStage background.');
break;
default:
break;
}
});
} catch (exception) {
hilog.error(DOMAIN_NUMBER, TAG, 'Failed to enable the listener for window stage event changes. Cause:' + JSON.stringify(exception));
}
hilog.info(DOMAIN_NUMBER, TAG, '%{public}s', 'Ability onWindowStageCreate');
// 设置UI加载
windowStage.loadContent('pages/Index', (err, data) => {
// ...
});
}
}
复制代码
Destroy状态在UIAbility实例销毁时触发。可以在onDestroy()回调中进行体系资源的释放、数据的保存等操作。
比方调用**terminateSelf()**方法停止当前UIAbility实例,从而完成UIAbility实例的销毁;或者用户使用最近使命列表关闭该UIAbility实例,完成UIAbility的销毁
UIAbility启动模式
singleton(单实例模式)
multiton(多实例模式)
specified(指定实例模式)
设置
模式设置通过module.json5实现
{
"module": {
...
"abilities": [
{
"launchType": "singleton",
...
}
]
}
}
复制代码
singleton
单实例模式,startAbility()启动。
再次调用startAbility()方法启动该UIAbility实例。由于启动的照旧原来的UIAbility实例,并未重新创建一个新的UIAbility实例,此时只会进入该UIAbility的onNewWant()回调,不会进入其onCreate()和onWindowStageCreate()生命周期回调
multiton
多实例模式,每次通过startAbility()启动会天生一个新的实例
每次启动都会进入onCreate()和onWindowStageCreate()
Specified
指定模式,
创建UIAbility实例之前,开辟者可以为该实例指定一个唯一的字符串Key,这样在调用startAbility()方法时,调用方就可以根据指定的Key来辨认响应请求的UIAbility实例。在EntryAbility中,调用startAbility()方法时,可以在want参数中增长一个自界说参数,比方instanceKey,以此来区分差别的UIAbility实例
在SpecifiedAbility启动之前,会先进入对应的AbilityStage的onAcceptWant()生命周期回调中,以获取该UIAbility实例的Key值。然后体系会主动匹配,假如存在与该UIAbility实例匹配的Key,则会启动与之绑定的UIAbility实例,并进入该UIAbility实例的onNewWant()回调函数;否则会创建一个新的UIAbility实例,并进入该UIAbility实例的onCreate()回调函数和onWindowStageCreate()回调函数
import { AbilityStage, Want } from '@kit.AbilityKit';
export default class MyAbilityStage extends AbilityStage {
onAcceptWant(want: Want): string {
// 在被调用方的AbilityStage中,针对启动模式为specified的UIAbility返回一个UIAbility实例对应的一个Key值
// 当前示例指的是module1 Module的SpecifiedAbility
if (want.abilityName === 'SpecifiedFirstAbility' || want.abilityName === 'SpecifiedSecondAbility') {
// 返回的字符串Key标识为自定义拼接的字符串内容
if (want.parameters) {
return `SpecifiedAbilityInstance_${want.parameters.instanceKey}`;
}
}
// ...
return 'MyAbilityStage';
}
}
复制代码
UIAbility的用法
指定启动页面
onWindowStageCreate(windowStage: window.WindowStage) {
StatusBarManager.immerseFullScreenAsync(windowStage)
// Main window is created, set main page for this ability
hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageCreate');
windowStage.loadContent('pages/Index', (err, data) => {
if (err.code) {
hilog.error(0x0000, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? '');
return;
}
hilog.info(0x0000, 'testTag', 'Succeeded in loading the content. Data: %{public}s', JSON.stringify(data) ?? '');
});
复制代码
可以参考如下例子实现启动闪屏,以及新手教程等逻辑
启动闪屏
UIAbility与UI的数据同步
事故通知机制
eventHub实现UIAbility内部通知机制,两种方式实现监听事故的处理
export default class EntryAbility extends UIAbility {
onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
// 获取eventHub
let eventhub = this.context.eventHub;
// 执行订阅操作
eventhub.on('event1', this.eventFunc);
//.....
eventFunc(argOne: Context, argTwo: Context): void {
hilog.info(DOMAIN_NUMBER, TAG, '1. ' + `${argOne}, ${argTwo}`);
return;
}
复制代码
eventhub.on('event1', (data: string) => {
// 触发事件,完成相应的业务操作
});
复制代码
通过emit实现事故的发布
// 不带参数触发自定义“event1”事件
this.context.eventHub.emit('event1');
// 带1个参数触发自定义“event1”事件
this.context.eventHub.emit('event1', 1);
// 带2个参数触发自定义“event1”事件
this.context.eventHub.emit('event1', 2, 'test');
// 开发者可以根据实际的业务场景设计事件传递的参数
复制代码
使用eventHub.off取消事故监听
import { UIAbility } from '@kit.AbilityKit';
export default class EntryAbility extends UIAbility {
// ...
onDestroy(): void {
this.context.eventHub.off('event1');
}
}
复制代码
UIAbility组件间的相互调度
启动应用内的UIAbility
调用方调用startAbility(),通过其中want来实现目标调用
private context = getContext(this) as common.UIAbilityContext;
let wantInfo: Want = {
deviceId: '', // deviceId为空表示本设备
bundleName: 'com.samples.stagemodelabilitydevelop',
moduleName: 'entry', // moduleName非必选
abilityName: 'FuncAbilityA',
parameters: {
// 自定义信息
info: '来自EntryAbility Page_UIAbilityComponentsInteractive页面'
},
};
this.context.startAbility(wantInfo).then(() => {
hilog.info(DOMAIN_NUMBER, TAG, 'startAbility success.');
}).catch((error: BusinessError) => {
hilog.error(DOMAIN_NUMBER, TAG, 'startAbility failed.');
});
复制代码
被调用方根据在UIAbility是否已启动,在onCreate或者onNewWant中实现相应want的处理,和参数吸收
import { AbilityConstant, UIAbility, Want } from '@kit.AbilityKit';
export default class FuncAbilityA extends UIAbility {
onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
// 接收调用方UIAbility传过来的参数
let funcAbilityWant = want;
let info = funcAbilityWant?.parameters?.info;
}
//...
}
复制代码
被调用方通过terminateSelf()来实现本方调用的竣事
context.terminateSelf((err) => {
if (err.code) {
hilog.error(DOMAIN_NUMBER, TAG, `Failed to terminate self. Code is ${err.code}, message is ${err.message}`);
return;
}
复制代码
启动应用内的UIAbility并得到效果
通过startAbilityForResult().then实现效果的吸收和处理
let context: common.UIAbilityContext = getContext(this) as common.UIAbilityContext; // UIAbilityContext
const RESULT_CODE: number = 1001;
let want: Want = {
deviceId: '', // deviceId为空表示本设备
bundleName: 'com.samples.stagemodelabilitydevelop',
moduleName: 'entry', // moduleName非必选
abilityName: 'FuncAbilityA',
parameters: {
// 自定义信息
info: '来自EntryAbility UIAbilityComponentsInteractive页面'
}
};
context.startAbilityForResult(want).then((data) => {
if (data?.resultCode === RESULT_CODE) {
// 解析被调用方UIAbility返回的信息
let info = data.want?.parameters?.info;
hilog.info(DOMAIN_NUMBER, TAG, JSON.stringify(info) ?? '');
if (info !== null) {
promptAction.showToast({
message: JSON.stringify(info)
});
}
}
hilog.info(DOMAIN_NUMBER, TAG, JSON.stringify(data.resultCode) ?? '');
}).catch((err: BusinessError) => {
hilog.error(DOMAIN_NUMBER, TAG, `Failed to start ability for result. Code is ${err.code}, message is ${err.message}`);
});
复制代码
被调用方通过terminateSelfWithResult()实现有关调用效果回调
let context: common.UIAbilityContext = getContext(this) as common.UIAbilityContext; // UIAbilityContext
const RESULT_CODE: number = 1001;
let abilityResult: common.AbilityResult = {
resultCode: RESULT_CODE,
want: {
bundleName: 'com.samples.stagemodelabilitydevelop',
moduleName: 'entry', // moduleName非必选
abilityName: 'FuncAbilityB',
parameters: {
info: '来自FuncAbility Index页面'
},
},
};
context.terminateSelfWithResult(abilityResult, (err) => {
if (err.code) {
hilog.error(DOMAIN_NUMBER, TAG, `Failed to terminate self with result. Code is ${err.code}, message is ${err.message}`);
return;
}
});
复制代码
启动UIAbility内的指定页面
区分被调用方冷启动照旧热启动
冷启动
\通过onCreate的want数据吸收,在onWindowStageCreate过程拉起相应的页面
import { AbilityConstant, Want, UIAbility } from '@kit.AbilityKit';
import { hilog } from '@kit.PerformanceAnalysisKit';
import { window, UIContext } from '@kit.ArkUI';
const DOMAIN_NUMBER: number = 0xFF00;
const TAG: string = '[EntryAbility]';
export default class EntryAbility extends UIAbility {
funcAbilityWant: Want | undefined = undefined;
uiContext: UIContext | undefined = undefined;
onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
// 接收调用方UIAbility传过来的参数
this.funcAbilityWant = want;
}
onWindowStageCreate(windowStage: window.WindowStage): void {
// Main window is created, set main page for this ability
hilog.info(DOMAIN_NUMBER, TAG, '%{public}s', 'Ability onWindowStageCreate');
// Main window is created, set main page for this ability
let url = 'pages/Index';
if (this.funcAbilityWant?.parameters?.router && this.funcAbilityWant.parameters.router === 'funcA') {
url = 'pages/Page_ColdStartUp';
}
windowStage.loadContent(url, (err, data) => {
// ...
});
}
}
复制代码
热启动
可以直接在onNewWant中跳转相应页面
import { AbilityConstant, Want, UIAbility } from '@kit.AbilityKit';
import { hilog } from '@kit.PerformanceAnalysisKit';
import type { Router, UIContext } from '@kit.ArkUI';
import type { BusinessError } from '@kit.BasicServicesKit';
const DOMAIN_NUMBER: number = 0xFF00;
const TAG: string = '[EntryAbility]';
export default class EntryAbility extends UIAbility {
funcAbilityWant: Want | undefined = undefined;
uiContext: UIContext | undefined = undefined;
// ...
onNewWant(want: Want, launchParam: AbilityConstant.LaunchParam): void {
if (want?.parameters?.router && want.parameters.router === 'funcA') {
let funcAUrl = 'pages/Page_HotStartUp';
if (this.uiContext) {
let router: Router = this.uiContext.getRouter();
router.pushUrl({
url: funcAUrl
}).catch((err: BusinessError) => {
hilog.error(DOMAIN_NUMBER, TAG, `Failed to push url. Code is ${err.code}, message is ${err.message}`);
});
}
}
}
}
复制代码
ExtensionAbility
体系ExtensionAbility
FormExtensionAbility FORM类型的ExtensionAbility组件,用于提供服务卡片的相干能力。
WorkSchedulerExtensionAbility, WORK_SCHEDULER类型的ExtensionAbility组件,用于提供延迟使命的相干能力。
InputMethodExtensionAbility,INPUT_METHOD类型ExtensionAbility组件,用于实现输入法应用的开辟。
BackupExtensionAbility,BACKUP类型的ExtensionAbility组件,用于提供备份及规复应用数据的能力。
DriverExtensionAbility,DRIVER类型的ExtensionAbility组件,用于提供驱动相干扩展框架。
EmbeddedUIExtensionAbility,EMBEDDED_UI类型的ExtensionAbility组件,用于提供跨历程界面嵌入的能力。
ShareExtensionAbilitymSHARE类型的ExtensionAbility组件,用于提供分享模板服务扩展的能力。
访问体系ExtensionAbility
在鸿蒙体系上自界说输入法
ExtensionAbility开辟
EmbeddedUIExtensionAbility和调用方使用的EmbeddedComponenty共同使用,开辟者可以在UIAbility的页面中通过EmbeddedComponent嵌入本应用的EmbeddedUIExtensionAbility提供的UI。EmbeddedUIExtensionAbility会在独立于UIAbility的历程中运行,完成其页面的布局和渲染。通常用于有历程隔离诉求的模块化开辟场景。
import { EmbeddedUIExtensionAbility, UIExtensionContentSession, Want } from '@kit.AbilityKit';
const TAG: string = '[ExampleEmbeddedAbility]'
export default class ExampleEmbeddedAbility extends EmbeddedUIExtensionAbility {
onCreate() {
console.log(TAG, `onCreate`);
}
onForeground() {
console.log(TAG, `onForeground`);
}
onBackground() {
console.log(TAG, `onBackground`);
}
onDestroy() {
console.log(TAG, `onDestroy`);
}
onSessionCreate(want: Want, session: UIExtensionContentSession) {
console.log(TAG, `onSessionCreate, want: ${JSON.stringify(want)}`);
let param: Record<string, UIExtensionContentSession> = {
'session': session
};
let storage: LocalStorage = new LocalStorage(param);
session.loadContent('pages/extension', storage);
}
onSessionDestroy(session: UIExtensionContentSession) {
console.log(TAG, `onSessionDestroy`);
}
}
复制代码
ExtensionUIAbility相干设置
{
"module": {
"extensionAbilities": [
{
"name": "EmbeddedUIExtAbility",
"icon": "$media:icon",
"description": "EmbeddedUIExtAbility",
"type": "embeddedUI",
"srcEntry": "./ets/EmbeddedUIExtAbility/EmbeddedUIExtAbility.ts"
},
]
}
}
复制代码
调用方使用embededComponent
import { Want } from '@kit.AbilityKit';
import { BusinessError } from '@kit.BasicServicesKit';
@Entry
@Component
struct Index {
@State message: string = 'Message: '
private want: Want = {
bundleName: "com.example.embeddeddemo",
abilityName: "EmbeddedUIExtAbility",
parameters: {
'ohos.extension.processMode.hostInstance': 'true'
}
}
build() {
Row() {
Column() {
Text(this.message).fontSize(30)
EmbeddedComponent(this.want, EmbeddedType.EMBEDDED_UI_EXTENSION)
.width('100%')
.height('90%')
.onTerminated((info: TerminationInfo) => {
this.message = 'Terminarion: code = ' + info.code + ', want = ' + JSON.stringify(info.want);
})
.onError((error: BusinessError) => {
this.message = 'Error: code = ' + error.code;
})
}
.width('100%')
}
.height('100%')
}
}
复制代码
AbilityStage
module级的组件,拥有onCreate()生命周期回调和onAcceptWant()、onConfigurationUpdated()、onMemoryLevel()事故回调。
import { AbilityStage, Want } from '@kit.AbilityKit';
export default class MyAbilityStage extends AbilityStage {
onCreate(): void {
// 应用的HAP在首次加载的时,为该Module初始化操作
}
onAcceptWant(want: Want): string {
// 仅specified模式下触发
return 'MyAbilityStage';
}
}
复制代码
module.json5的设置,moudule级组件界说在module对应分区
{
"module": {
"name": "entry",
"type": "entry",
"srcEntry": "./ets/myabilitystage/MyAbilityStage.ts",
...
}
}
复制代码
应用上下文Context
类型
UIAbilityContext
每个UIAbility中都包罗了一个Context属性,提供操作应用组件、获取应用组件的设置信息等能力
import { UIAbility, AbilityConstant, Want } from '@kit.AbilityKit';
export default class EntryAbility extends UIAbility {
onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
let uiAbilityContext = this.context;
//...
}
}
复制代码
ExtensionContext
以ServiceExtensionContext为例,表现后台服务的上下文环境,继续自ExtensionContext,提供后台服务相干的接口能力
import { ServiceExtensionAbility, Want } from '@kit.AbilityKit';
export default class ServiceExtAbility extends ServiceExtensionAbility {
onCreate(want: Want) {
let serviceExtensionContext = this.context;
//...
}
}
复制代码
AbilityStageContext
Module级别的Context,和基类Context相比,额外提供HapModuleInfo、Configuration等信息。
import { AbilityStage } from '@kit.AbilityKit';
export default class MyAbilityStage extends AbilityStage {
onCreate(): void {
let abilityStageContext = this.context;
//...
}
}
复制代码
ApplicationStageContext
应用级别的Context。ApplicationContext在基类Context的基础上提供了订阅应用内应用组件的生命周期的变革、订阅体系内存变革和订阅应用内体系环境的变革的能力,在UIAbility、ExtensionAbility、AbilityStage中均可以获取
import { UIAbility, AbilityConstant, Want } from '@kit.AbilityKit';
export default class EntryAbility extends UIAbility {
onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
let applicationContext = this.context.getApplicationContext();
//...
}
}
复制代码
获取文件路径
基类Context提供了获取应用文件路径的能力,ApplicationContext、AbilityStageContext、UIAbilityContext和ExtensionContext均继续该能力
import { common } from '@kit.AbilityKit';
import { hilog } from '@kit.PerformanceAnalysisKit';
import { promptAction } from '@kit.ArkUI';
const TAG: string = '[Page_Context]';
const DOMAIN_NUMBER: number = 0xFF00;
@Entry
@Component
struct Page_Context {
private context = getContext(this) as common.UIAbilityContext;
build() {
Column() {
//...
List({ initialIndex: 0 }) {
ListItem() {
Row() {
//...
}
.onClick(() => {
let applicationContext = this.context.getApplicationContext();
let cacheDir = applicationContext.cacheDir;
let tempDir = applicationContext.tempDir;
let filesDir = applicationContext.filesDir;
let databaseDir = applicationContext.databaseDir;
let bundleCodeDir = applicationContext.bundleCodeDir;
let distributedFilesDir = applicationContext.distributedFilesDir;
let preferencesDir = applicationContext.preferencesDir;
let cloudFileDir = applicationContext.cloudFileDir;
// 获取应用文件路径
let filePath = tempDir + 'test.txt';
hilog.info(DOMAIN_NUMBER, TAG, `filePath: ${filePath}`);
if (filePath !== null) {
promptAction.showToast({
message: filePath
});
}
})
}
//...
}
//...
}
//...
}
}
复制代码
获取和修改加密分区
在现实应用中,开辟者需要根据差别场景的需求选择符合的加密分区,从而保护应用数据的安全。通过公道使用差别级别的加密分区,可以有效提高应用数据的安全性
import { UIAbility, contextConstant, AbilityConstant, Want } from '@kit.AbilityKit';
export default class EntryAbility extends UIAbility {
onCreate(want: Want, launchParam: AbilityConstant.LaunchParam) {
// 存储普通信息前,切换到EL1设备级加密
this.context.area = contextConstant.AreaMode.EL1; // 切换area
// 存储普通信息
// 存储敏感信息前,切换到EL2用户级加密
this.context.area = contextConstant.AreaMode.EL2; // 切换area
// 存储敏感信息
// 存储敏感信息前,切换到EL3用户级加密
this.context.area = contextConstant.AreaMode.EL3; // 切换area
// 存储敏感信息
// 存储敏感信息前,切换到EL4用户级加密
this.context.area = contextConstant.AreaMode.EL4; // 切换area
// 存储敏感信息
}
}
复制代码
获取本应用中其他Module的Context
调用createModuleContext(moduleName:string)方法,获取本应用中其他Module的Context。获取到其他Module的Context之后,即可获取到相应Module的资源信息
import { common } from '@kit.AbilityKit';
import { promptAction } from '@kit.ArkUI';
let storageEventCall = new LocalStorage();
@Entry(storageEventCall)
@Component
struct Page_Context {
private context = getContext(this) as common.UIAbilityContext;
build() {
Column() {
//...
List({ initialIndex: 0 }) {
ListItem() {
Row() {
//...
}
.onClick(() => {
let moduleName2: string = 'entry';
let moduleContext: Context = this.context.createModuleContext(moduleName2);
if (moduleContext !== null) {
promptAction.showToast({
message: ('成功获取Context')
});
}
})
}
//...
}
//...
}
//...
}
}
复制代码
订阅历程内UIAbility生命周期变革
通过ApplicationContext提供的能力,可以订阅历程内UIAbility生命周期变革。当历程内的UIAbility生命周期变革时,如创建、可见/不可见、获焦/失焦、销毁等,会触发相应的回调函数。每次注册回调函数时,都会返回一个监听生命周期的ID,此ID会自增+1。当超过监听上限数量2^63-1时,会返回-1。
核心在this.lifecycleId = applicationContext.on(‘abilityLifecycle’, abilityLifecycleCallback)
import { AbilityConstant, AbilityLifecycleCallback, UIAbility, Want } from '@kit.AbilityKit';
import { hilog } from '@kit.PerformanceAnalysisKit';
import { window } from '@kit.ArkUI';
import { BusinessError } from '@kit.BasicServicesKit';
const TAG: string = '[LifecycleAbility]';
const DOMAIN_NUMBER: number = 0xFF00;
export default class LifecycleAbility extends UIAbility {
// 定义生命周期ID
lifecycleId: number = -1;
onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
// 定义生命周期回调对象
let abilityLifecycleCallback: AbilityLifecycleCallback = {
// 当UIAbility创建时被调用
onAbilityCreate(uiAbility) {
hilog.info(DOMAIN_NUMBER, TAG, `onAbilityCreate uiAbility.launchWant: ${JSON.stringify(uiAbility.launchWant)}`);
},
// 当窗口创建时被调用
onWindowStageCreate(uiAbility, windowStage: window.WindowStage) {
hilog.info(DOMAIN_NUMBER, TAG, `onWindowStageCreate uiAbility.launchWant: ${JSON.stringify(uiAbility.launchWant)}`);
hilog.info(DOMAIN_NUMBER, TAG, `onWindowStageCreate windowStage: ${JSON.stringify(windowStage)}`);
},
// 当窗口处于活动状态时被调用
onWindowStageActive(uiAbility, windowStage: window.WindowStage) {
hilog.info(DOMAIN_NUMBER, TAG, `onWindowStageActive uiAbility.launchWant: ${JSON.stringify(uiAbility.launchWant)}`);
hilog.info(DOMAIN_NUMBER, TAG, `onWindowStageActive windowStage: ${JSON.stringify(windowStage)}`);
},
// 当窗口处于非活动状态时被调用
onWindowStageInactive(uiAbility, windowStage: window.WindowStage) {
hilog.info(DOMAIN_NUMBER, TAG, `onWindowStageInactive uiAbility.launchWant: ${JSON.stringify(uiAbility.launchWant)}`);
hilog.info(DOMAIN_NUMBER, TAG, `onWindowStageInactive windowStage: ${JSON.stringify(windowStage)}`);
},
// 当窗口被销毁时被调用
onWindowStageDestroy(uiAbility, windowStage: window.WindowStage) {
hilog.info(DOMAIN_NUMBER, TAG, `onWindowStageDestroy uiAbility.launchWant: ${JSON.stringify(uiAbility.launchWant)}`);
hilog.info(DOMAIN_NUMBER, TAG, `onWindowStageDestroy windowStage: ${JSON.stringify(windowStage)}`);
},
// 当UIAbility被销毁时被调用
onAbilityDestroy(uiAbility) {
hilog.info(DOMAIN_NUMBER, TAG, `onAbilityDestroy uiAbility.launchWant: ${JSON.stringify(uiAbility.launchWant)}`);
},
// 当UIAbility从后台转到前台时触发回调
onAbilityForeground(uiAbility) {
hilog.info(DOMAIN_NUMBER, TAG, `onAbilityForeground uiAbility.launchWant: ${JSON.stringify(uiAbility.launchWant)}`);
},
// 当UIAbility从前台转到后台时触发回调
onAbilityBackground(uiAbility) {
hilog.info(DOMAIN_NUMBER, TAG, `onAbilityBackground uiAbility.launchWant: ${JSON.stringify(uiAbility.launchWant)}`);
},
// 当UIAbility迁移时被调用
onAbilityContinue(uiAbility) {
hilog.info(DOMAIN_NUMBER, TAG, `onAbilityContinue uiAbility.launchWant: ${JSON.stringify(uiAbility.launchWant)}`);
}
};
// 获取应用上下文
let applicationContext = this.context.getApplicationContext();
try {
// 注册应用内生命周期回调
this.lifecycleId = applicationContext.on('abilityLifecycle', abilityLifecycleCallback);
} catch (err) {
let code = (err as BusinessError).code;
let message = (err as BusinessError).message;
hilog.error(DOMAIN_NUMBER, TAG, `Failed to register applicationContext. Code is ${code}, message is ${message}`);
}
hilog.info(DOMAIN_NUMBER, TAG, `register callback number: ${this.lifecycleId}`);
}
//...
onDestroy(): void {
// 获取应用上下文
let applicationContext = this.context.getApplicationContext();
try {
// 取消应用内生命周期回调
applicationContext.off('abilityLifecycle', this.lifecycleId);
} catch (err) {
let code = (err as BusinessError).code;
let message = (err as BusinessError).message;
hilog.error(DOMAIN_NUMBER, TAG, `Failed to unregister applicationContext. Code is ${code}, message is ${message}`);
}
}
}
复制代码
want信息传递载体
显式与隐式
Want是一种对象,用于在应用组件之间传递信息。
其中,一种常见的使用场景是作为startAbility()方法的参数。比方,当UIAbilityA需要启动UIAbilityB并向UIAbilityB传递一些数据时,可以使用Want作为一个载体,将数据传递给UIAbilityB。
显示want
import { Want } from '@kit.AbilityKit';
let wantInfo: Want = {
deviceId: '', // deviceId为空表示本设备
bundleName: 'com.example.myapplication',
abilityName: 'FuncAbility',
}
复制代码
隐式want
import { Want } from '@kit.AbilityKit';
let wantInfo: Want = {
// uncomment line below if wish to implicitly query only in the specific bundle.
// bundleName: 'com.example.myapplication',
action: 'ohos.want.action.search',
// entities can be omitted
entities: [ 'entity.system.browsable' ],
uri: 'https://www.test.com:8080/query/student',
type: 'text/plain',
};
复制代码
want匹配原则
调用方传入的want参数,表明调用方需要执行的操作,并提供相干数据以及其他应用类型限制。
待匹配应用组件的skills设置,声明其具备的能力(module.json5设置文件中的skills标签参数)。
具体匹配参见官方文档.
应用启动使命AppStartup
应用启动时通常需要执行一系列初始化启动使命,假如将启动使命都放在应用主模块(即entry类型的Module)的UIAbility组件的onCreate生命周期中,那么只能在主线程中依次执行,不光影响应用的启动速度,而且当启动使命过多时,使命之间复杂的依赖关系还会使得代码难以维护。
AppStartup提供了一种简朴高效的应用启动方式,可以支持使命的异步启动,加快应用启动速度。同时,通过在一个设置文件中同一设置多个启动使命的执行顺序以及依赖关系,让执行启动使命的代码变得更加简洁清楚、容易维护。
启动框架支持以主动模式或手动模式执行启动使命,默认采用主动模式。在AbilityStage组件容器完成创建后开始加载开辟者设置的启动使命,并执行主动模式的启动使命。开辟者也可以在UIAbility创建完后调用startupManager.run方法,执行手动模式的启动使命
主要使用resources/base/profile下的profile设置相应的启动使命
{
"startupTasks": [
{
"name": "StartupTask_001",
"srcEntry": "./ets/startup/StartupTask_001.ets",
"dependencies": [
"StartupTask_002",
"StartupTask_003"
],
"runOnThread": "taskPool",
"waitOnMainThread": false
},
{
"name": "StartupTask_002",
"srcEntry": "./ets/startup/StartupTask_002.ets",
"dependencies": [
"StartupTask_004"
],
"runOnThread": "taskPool",
"waitOnMainThread": false
},
{
"name": "StartupTask_003",
"srcEntry": "./ets/startup/StartupTask_003.ets",
"dependencies": [
"StartupTask_004"
],
"runOnThread": "taskPool",
"waitOnMainThread": false
},
{
"name": "StartupTask_004",
"srcEntry": "./ets/startup/StartupTask_004.ets",
"runOnThread": "taskPool",
"waitOnMainThread": false
},
{
"name": "StartupTask_005",
"srcEntry": "./ets/startup/StartupTask_005.ets",
"dependencies": [
"StartupTask_006"
],
"runOnThread": "mainThread",
"waitOnMainThread": true,
"excludeFromAutoStart": true
},
{
"name": "StartupTask_006",
"srcEntry": "./ets/startup/StartupTask_006.ets",
"runOnThread": "mainThread",
"waitOnMainThread": false,
"excludeFromAutoStart": true
}
],
"configEntry": "./ets/startup/StartupConfig.ets"
}
复制代码
在module.json5中设定appStartup标签,指向设定的profile
{
"module": {
"name": "entry",
"type": "entry",
// ...
"appStartup": "$profile:startup_config", // 启动框架的配置文件
// ...
}
}
复制代码
configEntry用于指定StartupConfigEntry类型的实例实现启动使命的管理和状态监听
import { StartupConfig, StartupConfigEntry, StartupListener } from '@kit.AbilityKit';
import { hilog } from '@kit.PerformanceAnalysisKit';
import { BusinessError } from '@kit.BasicServicesKit';
export default class MyStartupConfigEntry extends StartupConfigEntry {
onConfig() {
hilog.info(0x0000, 'testTag', `onConfig`);
let onCompletedCallback = (error: BusinessError<void>) => {
hilog.info(0x0000, 'testTag', `onCompletedCallback`);
if (error) {
hilog.info(0x0000, 'testTag', 'onCompletedCallback: %{public}d, message: %{public}s', error.code, error.message);
} else {
hilog.info(0x0000, 'testTag', `onCompletedCallback: success.`);
}
};
let startupListener: StartupListener = {
'onCompleted': onCompletedCallback
};
let config: StartupConfig = {
'timeoutMs': 10000,
'startupListener': startupListener
};
return config;
}
}
复制代码
每个使命继续StartupTask,需要独立实现init和onDependencyCompleted
import { StartupTask, common } from '@kit.AbilityKit';
import { hilog } from '@kit.PerformanceAnalysisKit';
@Sendable
export default class StartupTask_001 extends StartupTask {
constructor() {
super();
}
async init(context: common.AbilityStageContext) {
hilog.info(0x0000, 'testTag', 'StartupTask_001 init.');
return 'StartupTask_001';
}
onDependencyCompleted(dependence: string, result: Object): void {
hilog.info(0x0000, 'testTag', 'StartupTask_001 onDependencyCompleted, dependence: %{public}s, result: %{public}s',
dependence, JSON.stringify(result));
}
}
复制代码
通过startupMgr.run可以实现使命的非主动启动
import { AbilityConstant, UIAbility, Want, startupManager } from '@kit.AbilityKit';
import { hilog } from '@kit.PerformanceAnalysisKit';
import { BusinessError } from '@kit.BasicServicesKit';
export default class EntryAbility extends UIAbility {
onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onCreate');
let startParams = ['StartupTask_005', 'StartupTask_006'];
try {
startupManager.run(startParams).then(() => {
console.log('StartupTest startupManager run then, startParams = ');
}).catch((error: BusinessError) => {
console.info("StartupTest promise catch error, error = " + JSON.stringify(error));
console.info("StartupTest promise catch error, startParams = "
+ JSON.stringify(startParams));
})
} catch (error) {
let errMsg = JSON.stringify(error);
let errCode: number = error.code;
console.log('Startup catch error , errCode= ' + errCode);
console.log('Startup catch error ,error= ' + errMsg);
}
}
// ...
}
复制代码
订阅体系
ApplicationContext订阅回调
ApplicationContext提供了注册回调函数以订阅体系环境变量的变革,并且可以通过调用相应的方法来打消该
ApplicationContext.on(type: ‘environment’, callback: EnvironmentCallback)
EnvironmentCallback.onConfigurationUpdated
EnvironmentCallback.onMemoryLevel
参考ApiReference
需要通过ApplicationContext.off(type: ‘environment’, callbackId: number)方法释放相干资源
AbilityStage订阅回调
使用AbilityStage.onConfigurationUpdate()回调方法订阅体系环境变量的变革。当体系环境变量发生变革时,会调用该回调方法。在该方法中,通过Configuration对象获取最新的体系环境设置信息
import { AbilityStage, Configuration } from '@kit.AbilityKit';
import { hilog } from '@kit.PerformanceAnalysisKit';
const TAG: string = '[MyAbilityStage]';
const DOMAIN_NUMBER: number = 0xFF00;
let systemLanguage: string | undefined; // 系统当前语言
export default class MyAbilityStage extends AbilityStage {
onCreate(): void {
systemLanguage = this.context.config.language; // Module首次加载时,获取系统当前语言
hilog.info(DOMAIN_NUMBER, TAG, `systemLanguage is ${systemLanguage}`);
//...
}
onConfigurationUpdate(newConfig: Configuration): void {
hilog.info(DOMAIN_NUMBER, TAG, `onConfigurationUpdate, language: ${newConfig.language}`);
hilog.info(DOMAIN_NUMBER, TAG, `onConfigurationUpdated systemLanguage is ${systemLanguage}, newConfig: ${JSON.stringify(newConfig)}`);
if (systemLanguage !== newConfig.language) {
hilog.info(DOMAIN_NUMBER, TAG, `systemLanguage from ${systemLanguage} changed to ${newConfig.language}`);
systemLanguage = newConfig.language; // 将变化之后的系统语言保存,作为下一次变化前的系统语言
}
}
}
复制代码
UIAbility订阅回调
UIAbility组件提供了UIAbility.onConfigurationUpdate()回调方法用于订阅体系环境变量的变革。当体系环境变量发生变革时,会调用该回调方法。在该方法中,通过Configuration对象获取最新的体系环境设置信息,而无需重启UIAbility。
import { AbilityConstant, Configuration, UIAbility, Want } from '@kit.AbilityKit';
import { hilog } from '@kit.PerformanceAnalysisKit';
const TAG: string = '[EntryAbility]';
const DOMAIN_NUMBER: number = 0xFF00;
let systemLanguage: string | undefined; // 系统当前语言
export default class EntryAbility extends UIAbility {
onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
systemLanguage = this.context.config.language; // UIAbility实例首次加载时,获取系统当前语言
hilog.info(DOMAIN_NUMBER, TAG, `systemLanguage is ${systemLanguage}`);
}
onConfigurationUpdate(newConfig: Configuration): void {
hilog.info(DOMAIN_NUMBER, TAG, `onConfigurationUpdated systemLanguage is ${systemLanguage}, newConfig: ${JSON.stringify(newConfig)}`);
if (systemLanguage !== newConfig.language) {
hilog.info(DOMAIN_NUMBER, TAG, `systemLanguage from ${systemLanguage} changed to ${newConfig.language}`);
systemLanguage = newConfig.language; // 将变化之后的系统语言保存,作为下一次变化前的系统语言
}
}
// ...
}
复制代码
ExtensionAbility订阅回调
ExtensionAbility组件提供了onConfigurationUpdate()回调方法用于订阅体系环境变量的变革。当体系环境变量发生变革时,会调用该回调方法。在该方法中,通过Configuration对象获取最新的体系环境设置信息。
import { FormExtensionAbility } from '@kit.FormKit';
import { Configuration } from '@kit.AbilityKit';
import { hilog } from '@kit.PerformanceAnalysisKit';
const TAG: string = '[EntryAbility]';
const DOMAIN_NUMBER: number = 0xFF00;
export default class EntryFormAbility extends FormExtensionAbility {
onConfigurationUpdate(config: Configuration) {
hilog.info(DOMAIN_NUMBER, TAG, '[EntryFormAbility] onConfigurationUpdate:' + JSON.stringify(config));
}
// ...
}
复制代码
Configuration
参考ApiReference Configuration
应用间跳转
类型
包括指向性跳转和通用意图跳转
指向性跳转
当前支持指定应用链接(保举):通过openLink或startAbility接口来指定应用链接,拉起目标应用页面。
通用意图跳转:
拉起方应用只申明跳转意图、而不指定具体跳转到哪一个应用,通过调用接口来拉起满足用户意图的垂类应用面板,该面板将展示目标方接入的垂域应用,由用户选择打开指定应用。
常见的通用意图跳转包括导航、分享、文件打开等高频场景,差别意图类型的跳转实现也有多种方式。
导航:支持导航、所在搜索、路线规划
文件打开:打开特定类型的文件
分享:支持文本、图片、视频等内容的跨应用分享
支付:支持实物商品和服务的支付
跳转URL格式
scheme://host[:port]/path/
scheme:协议名称。比方http、https等。
host:域名或IP地址。比方域名developer.huawei.com或IP地址127.0.0.1;
port:端标语。比方developer.huawei.com:80背面的80即为端标语。
path:路径,表现域名服务器上的目次或文件路径。比方developer.huawei.com/consumer/中consumer
应用毗连跳转机制
目标应用在设置文件中注册自己的URL,并对外提供URL。
拉起方应用在跳转接口中传入目标应用的URL等信息。
体系吸收到URL等相干信息,会寻找对应匹配项,并跳转至目标应用
支持Deep Linking 和App Linking
指向性跳转
跳转设置
调用方需要在module.json5设置queryparam
{
"module": {
//...
"querySchemes": [
"app1Scheme"
]
}
}
复制代码
被调用方需要在module.jso5设置支持的skills/uris
{
"module": {
//...
"abilities": [
{
//...
"skills": [
{
"uris": [
{
"scheme": "app1Scheme",
"host": "test.example.com",
"pathStartWith": "home"
}
]
}
]
}
]
}
}
复制代码
调用方可以通过canOpenLink来判断可跳转性
import { bundleManager } from '@kit.AbilityKit';
import { BusinessError } from '@kit.BasicServicesKit';
import { hilog } from '@kit.PerformanceAnalysisKit';
try {
let link = 'app1Scheme://test.example.com/home';
let canOpen = bundleManager.canOpenLink(link);
hilog.info(0x0000, 'testTag', 'canOpenLink successfully: %{public}s', JSON.stringify(canOpen));
} catch (err) {
let message = (err as BusinessError).message;
hilog.error(0x0000, 'testTag', 'canOpenLink failed: %{public}s', message);
}
复制代码
DeepLinking
目标应用需要在module.json5设置文件中声明URL skill。其中,uri字段的scheme的取值支持自界说,可以界说为任意不包罗特殊字符、非ohos开头的字符串。
{
"module": {
"abilities": [
{
"name": "EntryAbility",
"srcEntry": "./ets/entryability/EntryAbility.ets",
"icon": "$media:icon",
"label": "$string:EntryAbility_label",
"startWindowIcon": "$media:icon",
"startWindowBackground": "$color:start_window_background",
"skills": [
{
"entities": [
// entities须包含"entity.system.browsable"
"entity.system.browsable"
],
"actions": [
// actions须包含"ohos.want.action.viewData"
"ohos.want.action.viewData"
],
"uris": [
{
// scheme可以自定义
"scheme": "http",
// host须配置关联的域名
"host": "www.example.com",
// path可选,为了避免匹配到多个应用,建议配置该字段
"path": "path1"
}
]
}
]
}
]
}
}
复制代码
调用方使用openLink实现调用
import { common } from '@kit.AbilityKit';
import OpenLinkOptions from '@ohos.app.ability.OpenLinkOptions';
import { BusinessError } from '@ohos.base';
import hilog from '@ohos.hilog';
const TAG: string = '[UIAbilityComponentsOpenLink]';
const DOMAIN_NUMBER: number = 0xFF00;
@Entry
@Component
struct Index {
build() {
Button('start link', { type: ButtonType.Capsule, stateEffect: true })
.width('87%')
.height('5%')
.margin({ bottom: '12vp' })
.onClick(() => {
let context: common.UIAbilityContext = getContext(this) as common.UIAbilityContext;
let link: string = "http://www.example.com";
let openLinkOptions: OpenLinkOptions = {
appLinkingOnly: false
};
try {
context.openLink(link, openLinkOptions)
.then(() => {
hilog.info(DOMAIN_NUMBER, TAG, 'open link success.');
}).catch((err: BusinessError) => {
hilog.error(DOMAIN_NUMBER, TAG, `open link failed. Code is ${err.code}, message is ${err.message}`);
})
} catch (paramError) {
hilog.error(DOMAIN_NUMBER, TAG, `Failed to start link. Code is ${paramError.code}, message is ${paramError.message}`);
}
})
}
}
复制代码
通用意图跳转
通过startAbilityByType拉起垂类应用
接口startAbilityByType(API 11+) 是UIAbilityContext和UIExtensionContentSession提供的支持基于垂域业务类型拉起垂域面板,调用方通过指定特定的垂域业务类型即可拉起对应的垂域面板,在垂域面板上将展示目标方接入的垂域应用
比方,针对导航的跳转
调用方使用startAbilityByType和AbilityStartCallback
import { common } from '@kit.AbilityKit';
复制代码
let context = getContext(this) as common.UIAbilityContext;
let wantParam: Record<string, Object> = {
'sceneType': 1,
'destinationLatitude': 32.060844,
'destinationLongitude': 118.78315,
'destinationName': 'xx市xx路xx号',
'originName': 'xx市xx公园',
'originLatitude': 31.060844,
'originLongitude': 120.78315,
'vehicleType': 0
};
let abilityStartCallback: common.AbilityStartCallback = {
onError: (code: number, name: string, message: string) => {
console.log(`code:` + code + `name:` + name + `message:` + message);
}
}
context.startAbilityByType("navigation", wantParam, abilityStartCallback, (err) => {
if (err) {
console.error(`startAbilityByType fail, err: ${JSON.stringify(err)}`);
} else {
console.log(`success`);
}
});
复制代码
被调用放的应用需要声明相干能力
{
"abilities": [
{
"skills": [
{
"uris": [
{
"scheme": "maps", // 这里仅示意,应用需确保这里声明的的uri能被外部正常拉起
"host": "navigation",
"path": "",
"linkFeature": "Navigation" // 声明应用支持导航功能
},
{
"scheme": "maps", // 这里仅示意,应用需确保这里声明的的uri能被外部正常拉起
"host": "routePlan",
"path": "",
"linkFeature": "RoutePlan" // 声明应用支持路线规划功能
},
{
"scheme": "maps", // 这里仅示意,应用需确保这里声明的的uri能被外部正常拉起
"host": "search",
"path": "",
"linkFeature": "PlaceSearch" // 声明应用支持位置搜索功能
}
]
}
]
}
]
}
复制代码
在onCreate中吸收参数并实现相干导航关联逻辑
UIAbility::onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): voi
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/)
Powered by Discuz! X3.4