鸿蒙系统开发【应用接续】基本功能

应用接续

介绍

基于ArkTS扩展的声明式开发范式编程语言编写的一个分布式视频播放器,主要包括一个直播视频播放界面,实现视频播放时可以从一台设备迁移到另一台设备继续运行,来选择更合适的设备继续执行播放功能以及PAD视频播放时协同调用手机编辑发送弹幕功能。

效果预览

使用说明

  1. 准备手机端与平板端两台设备,并且登录同一华为账号,双端设备打开WI-FI和蓝牙,建议双端设备接入同一个局域网,可提升数据传输的速度
  2. 双端设备均安装此应用
  3. 滑动浏览手机端视频,打开平板端应用
  4. 点击平板端手机输入按钮,调起手机端输入内容,提交后平板端查看

具体实现

  1. 在实现协同接口前,应用需要申请协同所需的访问控制权ohos.permission.DISTRIBUTED_DATASYNC。 在requestPermissions字段中增加权限声明ohos.permission.DISTRIBUTED_DATASYNC

  2. 同时需要在应用首次启动时弹窗向用户申请授权,在用户手动允许授权后,应用才会真正获取相应权限,从而成功访问操作目标对象。 在EntryAbility类中实现以下函数,从而在调用时动态弹窗向用户申请权限。

    /*

    • Copyright (c) 2024 Huawei Device Co., Ltd.
    • Licensed under the Apache License, Version 2.0 (the "License");
    • you may not use this file except in compliance with the License.
    • You may obtain a copy of the License at
    • http://www.apache.org/licenses/LICENSE-2.0
      
    • Unless required by applicable law or agreed to in writing, software
    • distributed under the License is distributed on an "AS IS" BASIS,
    • WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    • See the License for the specific language governing permissions and
    • limitations under the License.
      */

    import { abilityAccessCtrl, AbilityConstant, bundleManager, Permissions, UIAbility, Want } from '@kit.AbilityKit';
    import { window } from '@kit.ArkUI';
    import { WindowUtil } from '../utils/WindowUtil';
    import Logger from '../utils/Logger';

    export default class EntryAbility extends UIAbility {
    contentStorage?: LocalStorage;

    onContinue(wantParam: Record<string, Object>) {
    Logger.info(wantParam.version.toString(), wantParam.targetDevice.toString());

     // Preparing to Migrate Data
     let activeLive: number = AppStorage.get<number>('activeLive') as number;
    
     // Save the data to be migrated in the 'data' field of wantParam.
     wantParam['activeLive'] = activeLive;
     // Setting the Source End Not to Exit
     wantParam["ohos.extra.param.key.supportContinueSourceExit"] = false;
    
     Logger.info(activeLive.toString());
     return AbilityConstant.OnContinueResult.AGREE
    

    }

    onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
    Logger.info('Ability onCreate');
    this.checkPermissions();

     // If the invoking reason is migration, set the status to migratable to cope with cold start (ensuring migration continuity)
     if (launchParam.launchReason === AbilityConstant.LaunchReason.CONTINUATION) {
       this.context.setMissionContinueState(AbilityConstant.ContinueState.ACTIVE, (result) => {
         Logger.info(JSON.stringify(result));
       });
     }
    
     // Cold start of the application: Restore the saved migration data
     if (launchParam.launchReason === AbilityConstant.LaunchReason.CONTINUATION) {
       // Restore migrated data from want
       let activeLive = want?.parameters?.activeLive;
       AppStorage.setOrCreate<number>('activeLive', activeLive as number);
       Logger.info(activeLive as string);
       // Explicit invocation of page restore
       this.contentStorage = new LocalStorage();
       Logger.info('Ability onCreate restoreWindowStage');
       this.context.restoreWindowStage(this.contentStorage);
     }
    

    }

    onNewWant(want: Want, launchParam: AbilityConstant.LaunchParam) {
    Logger.info('Ability onCreate');

     // If the invoking reason is migration, set the status to migratable to cope with hot start (ensuring migration continuity)
     if (launchParam.launchReason === AbilityConstant.LaunchReason.CONTINUATION) {
       this.context.setMissionContinueState(AbilityConstant.ContinueState.ACTIVE, (result) => {
         Logger.info(JSON.stringify(result));
       });
     }
    
     //During the warm start of an application: Restore the saved migration data
     if (launchParam.launchReason === AbilityConstant.LaunchReason.CONTINUATION) {
       // Restore migrated data from want
       let activeLive = want?.parameters?.activeLive;
       AppStorage.setOrCreate<number>('activeLive', activeLive as number);
       Logger.info(activeLive as string);
       // Explicit invocation of page restore
       this.contentStorage = new LocalStorage();
       Logger.info('Ability onNewWant restoreWindowStage');
       this.context.restoreWindowStage(this.contentStorage);
     }
    

    }

    // Check permission granting and dynamically apply for permissions
    async checkPermissions(): Promise<void> {
    const permissions: Array<Permissions> = ['ohos.permission.DISTRIBUTED_DATASYNC'];

     let grantStatus: abilityAccessCtrl.GrantStatus = await this.checkAccessToken(permissions[0]);
     // Verifying Permission Granting
     if (grantStatus === abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED) {
       // Granted
       Logger.info('Permission already granted.');
     } else {
       // Not granted. Dynamically apply for authorization in the dialog box displayed to the user
       let atManager = abilityAccessCtrl.createAtManager();
       try {
         atManager.requestPermissionsFromUser(this.context, ['ohos.permission.DISTRIBUTED_DATASYNC'], (err, data) => {
           Logger.info(JSON.stringify(data));
         });
       } catch (err) {
         Logger.error(JSON.stringify(err));
         return;
       }
     }
    

    }

    // Get the grant status of the current app's permissions
    async checkAccessToken(permission: Permissions): Promise<abilityAccessCtrl.GrantStatus> {
    let atManager = abilityAccessCtrl.createAtManager();
    let grantStatus: abilityAccessCtrl.GrantStatus = -1;

     // Obtains the token ID
     let tokenId: number = 0;
     try {
       let bundleInfo: bundleManager.BundleInfo =
         await bundleManager.getBundleInfoForSelf(bundleManager.BundleFlag.GET_BUNDLE_INFO_WITH_APPLICATION);
       let appInfo: bundleManager.ApplicationInfo = bundleInfo.appInfo;
       tokenId = appInfo.accessTokenId;
     } catch (err) {
       Logger.error(JSON.stringify(err));
     }
    
     try {
       grantStatus = await atManager.checkAccessToken(tokenId, permission);
     } catch (err) {
       Logger.error(JSON.stringify(err));
     }
     return grantStatus;
    

    }

    onDestroy(): void {
    Logger.info('Ability onDestroy');
    }

    onWindowStageCreate(windowStage: window.WindowStage): void {
    // Main window is created, set main page for this ability
    Logger.info('Ability onWindowStageCreate');

     WindowUtil.requestFullScreen(windowStage, this.context);
     WindowUtil.updateStatusBarColor(this.context, true);
    
     windowStage.loadContent('pages/LivePage', (err) => {
       if (err.code) {
         Logger.error(JSON.stringify(err) ?? '');
         return;
       }
       Logger.info('Succeeded in loading the content.');
     });
    

    }

    onWindowStageDestroy(): void {
    // Main window is destroyed, release UI related resources
    Logger.info('Ability onWindowStageDestroy');
    }

    onWindowStageRestore(windowStage: window.WindowStage): void {
    WindowUtil.requestFullScreen(windowStage, this.context);
    }

    onForeground(): void {
    // Ability has brought to foreground
    Logger.info('Ability onForeground');
    }

    onBackground(): void {
    // Ability has back to background
    Logger.info('Ability onBackground');
    }
    }

  3. 获取目标设备的设备ID。

  4. 在发起端设置目标组件参数,调用startAbilityForResult()接口启动目标端UIAbility,异步回调中的data用于接收目标端UIAbility停止自身后返回给调用方UIAbility的信息。

  5. 在目标端UIAbility任务完成后,调用terminateSelfWithResult()方法,将数据返回给发起端的UIAbility。

  6. 发起端UIAbility接收到目标端UIAbility返回的信息,对其进行处理。

以上就是本篇文章所带来的鸿蒙开发中一小部分技术讲解;想要学习完整的鸿蒙全栈技术。可以在结尾找我可全部拿到!

下面是鸿蒙的完整学习路线 ,展示如下:

除此之外,根据这个学习鸿蒙全栈学习路线,也附带一整套完整的学习【文档+视频】,内容包含如下

内容包含了:(ArkTS、ArkUI、Stage模型、多端部署、分布式应用开发、音频、视频、WebGL、OpenHarmony多媒体技术、Napi组件、OpenHarmony内核、鸿蒙南向开发、鸿蒙项目实战)等技术知识点。帮助大家在学习鸿蒙路上快速成长!

鸿蒙【北向应用开发+南向系统层开发】文档

鸿蒙【基础+实战项目】视频

鸿蒙面经

为了避免大家在学习过程中产生更多的时间成本,对比我把以上内容全部放在了↓↓↓想要的可以自拿喔!谢谢大家观看!

相关推荐
冰 河1 小时前
《Nginx核心技术》第16章:实现Nginx的高可用负载均衡
运维·nginx·程序员·负载均衡·高可用
爱打lan球的程序员3 小时前
redis分布式锁和lua脚本
数据库·redis·分布式
若兰幽竹4 小时前
【鸿蒙HarmonyOS NEXT】UIAbility的生命周期
harmonyos
yiyiy111yiy7 小时前
关于HarmonyOS的学习
前端·javascript·学习·华为·harmonyos
谢道韫6668 小时前
HarmonyOs DevEco Studio小技巧8--string的用法
开发语言·harmonyos
嵌入式lx9 小时前
Deveco_studio js/Arkts sdk 安装失败
javascript·openharmony·deveco_studio
流烟默11 小时前
Kafka【十三】消费者消费消息的偏移量
分布式·kafka·消费偏移量
Casual_Lei12 小时前
Spark的一些高级用法
大数据·分布式·spark
Android技术栈13 小时前
鸿蒙(API 12 Beta6版)GPU加速引擎服务【空域AI超分】
人工智能·华为·ai·harmonyos·鸿蒙·鸿蒙系统·openharmony
Android技术栈13 小时前
鸿蒙(API 12 Beta6版)超帧功能开发【ABR功能开发】
华为·移动开发·harmonyos·鸿蒙·鸿蒙系统·openharmony·abr