更多信息请访问:Harmonyos技术社区https://harmonyos.51cto.com1.相信大部分关注HarmonyOS的人都会来这里话说,我有对HarmonyOS的特点有一定的了解。从官网可以看到一些重点细化:“统一OS,灵活部署”,“硬件互助,资源共享”,“一次开发,多端部署”。在接下来的几期中,我想和大家一起探讨一下HarmonyOS的特性,找一些案例来学习和实践。目的是为了进一步巩固对特性的理解,进而灵活运用。本期通过分布式身份认证的功能,了解常用的通信方式。共享内容:需要在设备迁移或协作时显示可用设备列表。有一种方法可以在不单独获取设备或自己定义列表布局文件的情况下显示设备窗口。如何实现分布式身份认证和授权功能。案例来自codelabs官方示例分布式认证(Java),本帖整理分析,供大家学习交流。2、效果展示3、搭建环境,安装DevEcoStudio。具体请参考DevEcoStudio下载。搭建DevEcoStudio开发环境。DevEcoStudio开发环境依赖于网络环境。需要联网才能保证工具的正常使用。开发环境可根据以下两种情况进行配置:如果可以直接上网,只需要下载HarmonyOSSDK即可运行。如果网络不能直接访问Internet,则需要通过代理服务器访问。请参考配置开发环境。下载源码后,使用DevEcoStudio打开工程,运行模拟器。真机运行参见4.工程结构5.代码解释5.1显示传输设备列表的方法。该方法不需要单独获取设备,也不需要定义相应的布局文件来显示设备窗口。①向ContinuationRegisterManager注册一个跳跃能力,并获取分配给能力的注册token/***注册转移能力*registerContinuation**@paramcontext*@paramdeviceCallback*@paramshow是否显示可用的转移设备*/publicvoidregisterContinuation(AbilitySlicecontext,DeviceCallbackdeviceCallback,booleanshow){LogUtils.info("registerContinuation");if(continuationRegisterManager==null){this.deviceCallback=deviceCallback;this.show=show;continuationRegisterManager=context.getContinuationRegisterManager();//支持的设备类型ExtraParamsparams=newExtraParams();String[]devTypes=newString[]{ExtraParams.DEVICETYPE_SMART_PAD,ExtraParams.DEVICETYPE_SMART_WATCH,ExtraParams.DEVICETYPE_SMART_PHONE};params.setDevType(devTypes);//向ContinuationRegisterManager注册一个重定向能力,并获取分配给该能力的注册令牌//你可以使用IContinuationDeviceCallback来监听设备连接状态的变化即用户选择能力跳跃的设备,实现自己的处理逻辑。continuationRegisterManager.register(context.getBundleName(),params,callback,requestCallback);}else{if(show){//显示设备列表showContinuationDevice();}}}②传输完成后的状态回调,使用forlisteningCallbackfordeviceconnectionstatuschange//传输完成后的状态回调,提供监听设备连接状态变化的回调。privateIContinuationDeviceCallbackcallback=newIContinuationDeviceCallback(){@OverridepublicvoidonDeviceConnectDone(StringdeviceId,Stringval){LogUtils.info("onDeviceConnectDone");//设备连接完成后,将选中设备的任务提交到队列中,相当于点击设备待调用EventHandleventHandler=newEventHandler(EventRunner.getMainEventRunner());//提交任务到事件队列。eventHandler.postTask(newRunnable(){@Overridepublicvoidrun(){if(deviceCallback!=null){deviceCallback.onItemClick(deviceId);}//更新指定能力跳转成功的设备的连接状态continuationRegisterManager.updateConnectStatus(abilityToken,//表示需要更新连接状态的设备ID。deviceId,DeviceConnectState.IDLE.getState(),null);}});}@OverridepublicvoidonDeviceDisconnectDone(StringdeviceId){LogUtils.info("onDeviceDisconnectDone");}};③完成传输请求的回调,并显示可连接的设备transferred//流请求完成的回调,提供监听跳任务管理服务连接状态变化的回调。privateRequestCallbackrequestCallback=newRequestCallback(){@OverridepublicvoidonResult(intresult){abilityToken=result;if(show){//显示可转移设备showContinuationDevice();}}};/***显示可转移设备*showContinuation*/privatevoidshowContinuationDevice(){LogUtils。;//DisplaytransferabledevicescontinuationRegisterManager.showDeviceList(abilityToken,extraParams,null);}5.2实现一个分布式身份认证和授权的功能为了方便理解,发送请求的设备变成请求授权的设备,进行授权操作成为授权设备。RegisterManager自定义了CommonEvent接口,MainAbilitySlice实现了该接口,因此RegisterManager具有向MainAbilitySlice方向的通信能力。RegisterManager已经完成了对ConstUtil.ORDER_CODE类型的公共事件的订阅,因此可以接收该类型的公共事件。认证授权的完整流程:①在请求授权的设备上,RegisterManager提供注册设备传输能力的功能,并在设备完成状态回调中向执行队列提交一个“点击设备”任务联系。//传输完成后的状态回调,提供监听设备连接状态变化的回调。privateIContinuationDeviceCallbackcallback=newIContinuationDeviceCallback(){@OverridepublicvoidonDeviceConnectDone(StringdeviceId,Stringval){LogUtils.info("onDeviceConnectDone");//设备连接完成后,将选中设备的任务提交到队列中,相当于点击设备待调用EventHandleventHandler=newEventHandler(EventRunner.getMainEventRunner());//提交任务到事件队列。eventHandler.postTask(newRunnable(){@Overridepublicvoidrun(){if(deviceCallback!=null){deviceCallback.onItemClick(deviceId);}//更新指定能力跳转成功的设备的连接状态continuationRegisterManager.updateConnectStatus(abilityToken,//表示需要更新连接状态的设备ID。deviceId,DeviceConnectState.IDLE.getState(),null);}});}在MainAbilitySlice中,完成传输能力注册后,在“点击设备”的回调中,打开远程授权设备上的AuthrRemoteSlice页面,在同时传递了ConstUtil.DEVICE_ID和ConstUtil.ORDER_CODE(ConstUtil.START_ORDER)参数,并没有使用ConstUtil.START_ORDER。/***注册协作能力**@paramshow*/privatevoidregisterContinuation(booleanshow){LogUtils.info("registerContinuation");registerManager.registerContinuation(this,newRegisterManager.DeviceCallback(){@OverridepublicvoidonItemClick(StringdeviceId){LogUtils.info("onItemClick,deviceId:"+deviceId);//启动远程AblitystartRemoteAbility(deviceId);}},show);}/***启动远程FA**@paramdeviceId*/privatevoidstartRemoteAbility(StringdeviceId){LogUtils.info("startRemoteAbility");DialogUtil.showToast(getContext(),"请求已发送,等待对方确认。");//StringlocalDeviceId=KvManagerFactory.getInstance().createKvManager(newKvManagerConfig(this)).getLocalDeviceInfo().getId();Intentintent=newIntent();Operationoperation=newIntent.OperationBuilder().withDeviceId(deviceId).withBundleName(getBundleName()).withAbilityName(MainAbility.class.getName())//路由指向授权设备的认证页面.withAction(MainAbility.ACTION).withFlags(Intent.FLAG_ABILITYSLICE_MULTI_DEVICE).build();intent.setOperation(operation);intent.setParam(ConstUtil.DEVICE_ID,localDeviceId);//启动远程FA指令码intent.setParam(ConstUtil.ORDER_CODE,ConstUtil.START_ORDER);startAbility(intent);}②授权设备上的AuthrRemoteSlice页面后打开后,点击Allow或NotAllow时,请求分发权限后,请求授权的设备的MainAbility开启。privatevoidinitViewData(){LogUtils.info("initViewData");findComponentById(ResourceTable.Id_yes_btn).setClickedListener(component->{sendMessage(AUTH_TYPE1);});findComponentById(ResourceTable.Id_no_btn).setClickedListener(THcomponent->{AUsend_Tessage();});}privatevoidsendMessage(inttype){LogUtils.info("sendMessage");//从MainAbilityHPermissionhPermission中获取HPermission实例hPermission=((MainAbility)getAbility()).getPermission();//如果用户允许分布式权限,设置按钮可以使用hPermission.requestPermissions(this,()->{//buttonEnabledfindComponentById(ResourceTable.Id_yes_btn).setEnabled(false);findComponentById(ResourceTable.Id_no_btn).setEnabled(false);//打开页面就可以了请求端startRemoteAbility(type);});}/***请求授权端开启MainAbility**@paramtype同意授权*/privatevoidstartRemoteAbility(inttype){LogUtils.info("startRemoteAbility");DialogUtil.showToast(getContext(),type==AUTH_TYPE1?""允许播放game":"拒绝玩游戏");Intentintent=newIntent();Operationoperation=newIntent.OperationBuilder().withDeviceId(remoteDeviceId==null?"":remoteDeviceId).withBundleName(getBundleName()).withAbilityName(MainAbility.class.getName()).withFlags(Intent.FLAG_ABILITYSLICE_MULTI_DEVICE).build();intent.setOperation(operation);//授权码intent.setParam(ORDER_CODE,type);startAbility(intent);//关闭当前宿主AbilitygetUITaskDispatcher().delayDispatch(()->terminateAbility(),DELAY);}③在请求授权的设备上,由于MainAbility设置为单例模式("launchType":"singleton")并且已经实例化,请求进入onNewIntent函数config.json{..."orientation":"unspecified","visible":true,"name":"com.buty.javadistributeddemo.MainAbility","icon":"$media:icon","description":"$string:mainability_description","label":"$string:entry_MainAbility","type":"page","launchType":"singleton"}在onNewIntent函数中,通过CommonEventManager发布一个ConstUtil.ORDER_CODE类型的事件,RegisterManager接收并处理该事件。如何处理?事件通过RegisterManager.CommonEvent传递给实现RegisterManager.CommonEvent接口的MainAbilitySlice,最后显示对端设备的授权结果(允许/不允许)/***能力设置为单例模式*创建时,如果instance已经存在,触发这个函数**@paramintent*/@OverrideprotectedvoidonNewIntent(Intentintent){LogUtils.info("onNewIntent");super.onNewIntent(intent);//是否允许intcode=intent.getIntParam(ConstUtil.ORDER_CODE,0);//StringdeviceId=intent.getStringParam(ConstUtil.DEVICE_ID);sendCommonEvent(code,deviceId);}MainAbilitySlice收到消息/***factRegisterManager的CommonEvent接口**@paramcodecode*@paramdeviceIddeviceId*/@OverridepublicvoidonReceiveEvent(intcode,StringdeviceId){LogUtils.info("onReceiveEvent,code:"+code);switch(code){//同意allowgamestobeplayedcaseConstUtil.AUTH_TYPE1://start.setVisibility(Component.HIDE);tips.setVisibility(Component.VISIBLE);tips.setText("Authorized,youcanstartthegame");break;//RefusetoplaygamescaseConstUtil.AUTH_TYPE2:tips.setVisibility(Component.VISIBLE);//DialogUtil.exitDialog(getAbility());tips.setText("Rejected,notallowedtoplay");break;default:break;}}6.思考总结分布式常用的通信方式:1.Intent直接传参(intent.setParam(ORDER_CODE,type))2.公共事件订阅/发布方法(Intent封装成CommonEventData)3.自定义接口方法(RegisterManager.CommonEvent)文章相关附件可点击下载原文链接如下https://harmonyos.51cto.com/resource/1574更多信息请访问:与华为官方共建的Harmonyos技术社区https://harmonyos.51cto.com
