HarmonyOS 鸿蒙Next应用接续开发分享|逸校园开发实践
HarmonyOS 鸿蒙Next应用接续开发分享|逸校园开发实践
HarmonyOS NEXT新特性中,应用接续功能可以极大地提升用户在多设备间的使用体验,实现服务不中断。以下是一些关键的开发步骤和实践分享:
开发建议:参考示例代码:HarmonyOS_Samples/ContinuePublish
约束条件:
需同时满足以下条件,才能使用该功能:
- 双端设备需要登录同一华为账号。
- 双端设备需要打开Wi-Fi和蓝牙开关。
条件允许时,建议双端设备接入同一个局域网,可提升数据传输的速度。
- 应用接续只能在同应用(UIAbility)之间触发,双端设备都需要有该应用。
一、开发步骤
1. 启用应用接续能力
在module.json5文件中,为需要支持接续的UIAbility配置continuable属性为true,以启用应用接续能力。
{
“module”: {
“abilities”: [
{
“name”: “com.example.harmony.MainAbility”,
“label”: “$string:app_name”,
“description”: “$string:mainability_description”,
“icon”: “$media:icon”,
“visible”: true,
“launchType”: “standard”,
“orientation”: “portrait”,
“continuable”: true
}
]
}
}
2. 基础数据&文件资产迁移
对于图片、文档等文件类数据,可以将其转换为ArrayBuffer类型,并保存在分布式文件目录下。
writeDistributedFile(buf: ArrayBuffer, displayName: string): void {
let distributedDir: string = this.context.distributedFilesDir;
let fileName: string = ‘/’ + displayName;
let filePath: string = distributedDir + fileName;
try {
let file = fs.openSync(filePath, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE);
hilog.info(0x0000, ‘[AddPic]’, ‘Create file success.’);
fs.writeSync(file.fd, buf);
fs.closeSync(file.fd);
} catch (error) {
let err: BusinessError = error as BusinessError;
hilog.info(0x0000, ‘[AddPic]’,
Failed to openSync / writeSync / closeSync. Code: ${err.code}, message: ${err.message}
);}
}
3. 创建和保存分布式数据对象
在源端UIAbility的onContinue()接口中创建分布式数据对象并保存数据。
async onContinue(wantParam: Record<string, Object | undefined>): Promise<AbilityConstant.OnContinueResult> {
wantParam.imageUriArray = JSON.stringify(AppStorage.get<Array<PixelMap>>(‘imageUriArray’));
try {
let sessionId: string = distributedDataObject.genSessionId();
wantParam.distributedSessionId = sessionId;
let imageUriArray = AppStorage.get<Array<ImageInfo>>(‘imageUriArray’);
let assets: commonType.Assets = [];
if (imageUriArray) {
for (let i = 0; i < imageUriArray.length; i++) {
let append = imageUriArray[i];
let attachment: commonType.Asset = this.getAssetInfo(append);
assets.push(attachment);
}
}
let contentInfo: ContentInfo = new ContentInfo(
AppStorage.get(‘mainTitle’),
AppStorage.get(‘textContent’),
AppStorage.get(‘imageUriArray’),
AppStorage.get(‘isShowLocalInfo’),
AppStorage.get(‘isAddLocalInfo’),
AppStorage.get(‘selectLocalInfo’),
assets
);
let source = contentInfo.flatAssets();
this.distributedObject = distributedDataObject.create(this.context, source);
this.distributedObject.setSessionId(sessionId);
await this.distributedObject.save(wantParam.targetDevice as string).catch((err: BusinessError) => {
hilog.info(0x0000, ‘[EntryAbility]’,
Failed to save. Code: ${err.code}, message: ${err.message}
);});
} catch (error) {
hilog.error(0x0000, ‘[EntryAbility]’, ‘distributedDataObject failed’,
code ${(error as BusinessError).code}
);}
return AbilityConstant.OnContinueResult.AGREE;
}
4. 基础数据&文件资产恢复
在对端设备UIAbility的onCreate()/onNewWant()中调用restoreDistributedObject()方法,通过加入与源端一致的分布式数据对象组网进行数据恢复。
onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
hilog.info(0x0000, ‘[EntryAbility]’, ‘Ability onCreate’);
this.restoreDistributedObject(want, launchParam);
}
onNewWant(want: Want, launchParam: AbilityConstant.LaunchParam): void {
hilog.info(0x0000, ‘[EntryAbility]’, ‘Ability onNewWant’);
this.restoreDistributedObject(want, launchParam);
}
async restoreDistributedObject(want: Want, launchParam: AbilityConstant.LaunchParam): Promise<void> {
if (launchParam.launchReason !== AbilityConstant.LaunchReason.CONTINUATION) {
return;
}
let mailInfo: ContentInfo = new ContentInfo(undefined, undefined, [], undefined, undefined, undefined, undefined);
this.distributedObject = distributedDataObject.create(this.context, mailInfo);
this.distributedObject.on(‘status’, (sessionId: string, networkId: string, status: ‘online’ | ‘offline’ | ‘restored’) => {
hilog.info(0x0000, ‘[EntryAbility]’,
status changed, sessionId: ${sessionId}
);hilog.info(0x0000, ‘[EntryAbility]’,
status changed, status: ${status}
);hilog.info(0x0000, ‘[EntryAbility]’,
status changed, networkId: ${networkId}
);if (status === ‘restored’) {
if (!this.distributedObject) {
return;
}
AppStorage.setOrCreate(‘mainTitle’, this.distributedObject[‘mainTitle’]);
AppStorage.setOrCreate(‘textContent’, this.distributedObject[‘textContent’]);
AppStorage.setOrCreate(‘isShowLocalInfo’, this.distributedObject[‘isShowLocalInfo’]);
AppStorage.setOrCreate(‘isAddLocalInfo’, this.distributedObject[‘isAddLocalInfo’]);
AppStorage.setOrCreate(‘selectLocalInfo’, this.distributedObject[‘selectLocalInfo’]);
AppStorage.setOrCreate(‘attachments’, this.distributedObject[‘attachments’]);
let attachments = this.distributedObject[‘attachments’] as commonType.Assets;
hilog.info(0x0000, ‘[EntryAbility]’,
attachments: ${JSON.stringify(this.distributedObject['attachments'])}
);for (const attachment of attachments) {
this.fileCopy(attachment);
}
AppStorage.setOrCreate<Array<ImageInfo>>(‘imageUriArray’, this.imageUriArray);
}
});
let sessionId: string = want.parameters?.distributedSessionId as string;
this.distributedObject.setSessionId(sessionId);
this.context.restoreWindowStage(new LocalStorage());
}
5. 从分布式文件目录路径下读取文件
接续过来的图片,需要从分布式文件目录路径下读取所需的文件,经处理后,转化成需要的数据类型。
private fileCopy(attachment: commonType.Asset): void {
let filePath: string = this.context.distributedFilesDir + ‘/’ + attachment.name;
let savePath: string = this.context.filesDir + ‘/’ + attachment.name;
try {
if (fs.accessSync(filePath)) {
let saveFile = fs.openSync(savePath, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE);
let file = fs.openSync(filePath, fs.OpenMode.READ_WRITE);
let buf: ArrayBuffer = new ArrayBuffer(Number(attachment.size) * 1024);
let readSize = 0;
let readLen = fs.readSync(file.fd, buf, { offset: readSize });
let sourceOptions: image.SourceOptions = { sourceDensity: 120 };
let imageSourceApi: image.ImageSource = image.createImageSource(buf, sourceOptions);
this.imageUriArray.push({
imagePixelMap: imageSourceApi.createPixelMapSync(),
imageName: attachment.name
});
while (readLen > 0) {
readSize += readLen;
fs.writeSync(saveFile.fd, buf);
readLen = fs.readSync(file.fd, buf, { offset: readSize });
}
fs.closeSync(file);
fs.closeSync(saveFile);
hilog.info(0x0000, ‘[EntryAbility]’, attachment.name + ‘synchronized successfully.’);
}
} catch (error) {
let err: BusinessError = error as BusinessError;
hilog.error(0x0000, ‘[EntryAbility]’,
DocumentViewPicker failed with err: ${JSON.stringify(err)}
);}
}
二、开发TIPS:
可以在需要开启接续的页面启用接续功能,离开该页面即关闭
onPageShow() {
// 进入该页面时,将应用设置为可迁移状态
this.context.setMissionContinueState(AbilityConstant.ContinueState.ACTIVE, (result) => {
console.info('setMissionContinueState ACTIVE result: ', JSON.stringify(result));
});
this.isBasicMode = true;
}
onPageHide(): void {
this.context.setMissionContinueState(AbilityConstant.ContinueState.INACTIVE, (result) => {
console.info('setMissionContinueState ACTIVE result: ', JSON.stringify(result));
});
}
接续功能可以开启应用版本检测,避免升级带来的接续不兼容闪退等问题:
onContinue(wantParam: Record<string, Object>) {
let versionDst = wantParam.version; // 获取迁移对端应用的版本号
let versionSrc: number = bundleManager.getBundleInfoForSelfSync(bundleManager.BundleFlag.GET_BUNDLE_INFO_DEFAULT).versionCode; // 获取迁移源端即本端应用的版本号
if (versionDst > versionSrc) { // 兼容性校验
// 兼容性校验不满足
return AbilityConstant.OnContinueResult.MISMATCH;
}
console.info(onContinue version = ${wantParam.version}, targetDevice: ${wantParam.targetDevice}
)
// 迁移数据保存
let continueInput = AppStorage.get<string>(“ContinueProperty”);
if (continueInput) {
// 将要迁移的数据保存在wantParam的自定义字段(如:data)中;
wantParam[“data”] = continueInput;
}
三、效果:
更多关于HarmonyOS 鸿蒙Next应用接续开发分享|逸校园开发实践的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html
更多关于HarmonyOS 鸿蒙Next应用接续开发分享|逸校园开发实践的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html
在HarmonyOS鸿蒙Next应用接续开发中,针对逸校园的开发实践,核心在于充分利用鸿蒙系统的分布式特性和系统能力。
首先,鸿蒙系统支持多设备协同工作,这意味着开发者可以在逸校园应用中实现跨设备的无缝接续。例如,学生在手机上查看课程信息后,可以无缝切换到平板或电脑上继续深入学习,而无需重新加载或登录。
其次,鸿蒙系统提供了丰富的系统能力接口,如位置服务、通知服务、多模输入等,这些都可以被集成到逸校园应用中,以提升用户体验。例如,通过位置服务,应用可以自动推荐附近的图书馆或自习室;通过通知服务,可以及时提醒学生上课或考试等重要事件。
在开发实践中,需要重点关注鸿蒙系统的应用框架、分布式数据库、分布式文件系统等技术点,这些是实现跨设备接续和数据同步的关键。
此外,鸿蒙系统还支持丰富的UI组件和动画效果,开发者可以利用这些组件和效果,打造更加美观和流畅的用户界面。
总之,在HarmonyOS鸿蒙Next应用接续开发中,通过充分利用鸿蒙系统的分布式特性和系统能力,可以为逸校园应用带来更加出色的跨设备接续体验和更丰富的功能。
如果问题依旧没法解决请联系官网客服,官网地址是:https://www.itying.com/category-93-b0.html