1/* 2 * Copyright (c) 2025 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16import rpc from '@ohos.rpc'; 17import Want from '@ohos.app.ability.Want'; 18import common from '@ohos.app.ability.common'; 19import hilog from '@ohos.hilog'; 20import { BusinessError } from '@kit.BasicServicesKit'; 21import { obtainResult } from '../../pages/Index'; 22import { util } from '@kit.ArkTS'; 23 24const TAG = 'ClientIpc_App1'; 25const DOMAIN = 0x0000; 26 27let proxy: rpc.IRemoteObject | undefined; 28let connectid: number | undefined; 29let want: Want = { 30 bundleName: 'com.samples.ipc_service', 31 abilityName: 'IpcServiceExtAbility', 32} 33 34// Parcelable对象 35class MyParcelable implements rpc.Parcelable { 36 public num: number = 0; 37 public str: string = ''; 38 39 constructor(num: number, str: string) { 40 this.num = num; 41 this.str = str; 42 } 43 44 marshalling(messageSequence: rpc.MessageSequence): boolean { 45 messageSequence.writeInt(this.num); 46 messageSequence.writeString(this.str); 47 return true; 48 } 49 50 unmarshalling(messageSequence: rpc.MessageSequence): boolean { 51 this.num = messageSequence.readInt(); 52 this.str = messageSequence.readString(); 53 return true; 54 } 55} 56 57export class ClientIpc { 58 static bindAbi(context: 59 common.UIAbilityContext, callback: () => void) { 60 connectIpc(context, callback); 61 } 62 63 static unBindAbi(context: common.UIAbilityContext) { 64 disConnectIpc(context); 65 } 66 67 // 处理Parcelable数据,调用sendData发送至服务端 68 static sendParcelable(str: string) { 69 if (proxy == undefined) { 70 hilog.info(DOMAIN, TAG, 'undefined proxy'); 71 return; 72 } 73 let option = new rpc.MessageOption(); 74 let data = rpc.MessageSequence.create(); 75 let reply = rpc.MessageSequence.create(); 76 77 // 取决于MyParcelable类如何定义,或需要序列化时准备传递什么数据类型,本示例中MyParcelable是以number和string为例,且服务端接收string 78 let parcelable = new MyParcelable(1, str); 79 try { 80 // 进行校验 81 data.writeInterfaceToken(proxy.getDescriptor()); 82 // 写入Parcelable 83 data.writeParcelable(parcelable); 84 } catch (error) { 85 let e: BusinessError = error as BusinessError; 86 hilog.error(DOMAIN, TAG, 'ipc write parcelable fail, errorCode ' + e.code + 'errorMessage:' + e.message); 87 } 88 89 sendData(proxy, 1001, data, reply, option); 90 } 91 92 // 处理arraybuffer数据,调用sendData发送至服务端 93 static sendArrayBuffer(str: string) { 94 if (proxy == undefined) { 95 hilog.info(DOMAIN, TAG, 'undefined proxy'); 96 return; 97 } 98 let option = new rpc.MessageOption(); 99 let data = rpc.MessageSequence.create(); 100 let reply = rpc.MessageSequence.create(); 101 102 // 将str转为ArrayBuffer 103 const encoder = new util.TextEncoder('utf-8'); 104 105 // 使用TextEncoder将字符串编码为Uint8Array 106 const uint8Array = encoder.encodeInto(str); 107 108 // 将Uint8Array转换为ArrayBuffer 109 const arrayBuffer = uint8Array.buffer; 110 try { 111 // 进行校验 112 data.writeInterfaceToken(proxy.getDescriptor()); 113 // 写入ArrayBuffer 114 hilog.error(DOMAIN, TAG, 'arraybuffer:' + uint8Array.toString()); 115 data.writeArrayBuffer(arrayBuffer, rpc.TypeCode.UINT8_ARRAY); 116 } catch (error) { 117 let e: BusinessError = error as BusinessError; 118 hilog.error(DOMAIN, TAG, 'ipc write parcelable fail, errorCode ' + e.code + 'errorMessage:' + e.message); 119 } 120 121 sendData(proxy, 1002, data, reply, option); 122 } 123} 124 125// 连接服务端 126function connectIpc(context: common.UIAbilityContext, callback: () => void) { 127 let connect: common.ConnectOptions = { 128 onConnect: (elementName, remoteProxy) => { 129 hilog.info(DOMAIN, TAG, 'IpcClient:onConnect.callend(server),elementName:' + 130 JSON.stringify(elementName)); 131 proxy = remoteProxy; 132 obtainResult.result = 'success'; 133 callback(); 134 }, 135 onDisconnect: (elementName) => { 136 hilog.info(DOMAIN, TAG, 'IpcClient onDisconnect:' + elementName); 137 }, 138 onFailed: (code: number) => { 139 obtainResult.result = 'error ' + code; 140 hilog.info(DOMAIN, TAG, 'IpcClient onFailed,code:' + code); 141 callback(); 142 }, 143 } 144 145 connectid = context.connectServiceExtensionAbility(want, connect); 146 hilog.info(DOMAIN, TAG, 'IpcClient connectid:' + connectid); 147} 148 149function disConnectIpc(context: common.UIAbilityContext) { 150 if (connectid != undefined) { 151 context.disconnectServiceExtensionAbility(connectid); 152 proxy = undefined; 153 } 154} 155 156// 发送信息,arraybuffer和parcelable均调用此处发送至服务端 157function sendData(proxy: rpc.IRemoteObject, code: number, data: rpc.MessageSequence, reply: rpc.MessageSequence, 158 options: rpc.MessageOption) { 159 if (proxy == undefined) { 160 hilog.info(DOMAIN, TAG, 'undefined proxy'); 161 return; 162 } 163 // 用连接服务成功后返回的对象proxy,进行消息发送 164 proxy.sendMessageRequest(code, data, reply, options) 165 .then((result: rpc.RequestResult) => { 166 if (result.errCode === 0) { 167 hilog.info(DOMAIN, TAG, 'sendMessageRequest got result'); 168 try { 169 let rsp = result.reply.readString(); 170 hilog.info(DOMAIN, TAG, 'IpcClient result.' + rsp); 171 } catch (error) { 172 let e: BusinessError = error as BusinessError; 173 hilog.error(DOMAIN, TAG, 'rpc read exception fail, error is ' + e); 174 } 175 } else { 176 hilog.error(DOMAIN, TAG, 'RPCTest: sendMessageRequest failed, errCode: ' + result.errCode); 177 } 178 }).catch((e: Error) => { 179 hilog.error(DOMAIN, TAG, 'RPCTest: sendMessageRequest got exception: ' + e); 180 }).finally(() => { 181 hilog.info(DOMAIN, TAG, 'RPCTest: sendMessageRequest ends, reclaim parcel'); 182 data.reclaim(); 183 reply.reclaim(); 184 }); 185} 186