1/* 2 * Copyright (c) 2024 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 util from '@ohos.util'; 17import notificationManager from '@ohos.notificationManager'; 18import inputEventClient from '@ohos.multimodalInput.inputEventClient'; 19import WantAgent, { WantAgent as _WantAgent } from '@ohos.wantAgent'; 20import CommonEventManager from '@ohos.commonEvent'; 21import Base from '@ohos.base'; 22import type context from '@ohos.app.ability.common'; 23import image from '@ohos.multimedia.image'; 24import GlobalContext from '../common/GlobalContext'; 25 26const TAG: string = 'InjectNotice'; 27const LABEL: string = 'inject notice'; 28const EVENT_NAME: string = 'event_inject_close_notice'; 29export const NOTICE_ID: number = 100; 30 31export enum InjectNoticeStaus { 32 DEFAULT = 0, 33 OPENING = 1, 34 SERVER_CLOSE = 2, 35 MAN_CLOSE = 3, 36}; 37 38class InjectNoticeUtil { 39 status: InjectNoticeStaus = InjectNoticeStaus.DEFAULT; 40 isInit: boolean = false; 41 removalWantAgentObj: _WantAgent = null; 42 removalWantAgentInfo: WantAgent.WantAgentInfo = { 43 wants: [ 44 { 45 action: EVENT_NAME, 46 parameters: { 47 noticeId: NOTICE_ID, 48 noticeLabel: LABEL, 49 }, 50 } 51 ], 52 operationType: WantAgent.OperationType.SEND_COMMON_EVENT, 53 requestCode: 0, 54 wantAgentFlags: [WantAgent.WantAgentFlags.CONSTANT_FLAG], 55 }; 56 commonEventSubscriber: CommonEventManager.CommonEventSubscriber = null; 57 capsuleIcon: image.PixelMap | null = null; 58 constructor() { 59 60 } 61 62 async init(): Promise<void> { 63 console.info(TAG, `init begin`); 64 if (this.isInit) { 65 return; 66 } 67 this.initRemovalWantAgent(); 68 this.createCommonEventSubscriber(); 69 let systemLiveViewSubscriber: notificationManager.SystemLiveViewSubscriber = { 70 onResponse: this.onLiveNoticeResponseCallback, 71 }; 72 console.info(TAG, 'subscribeSystemLiveView begin'); 73 notificationManager.subscribeSystemLiveView(systemLiveViewSubscriber).then(() => { 74 console.info(TAG, 'subscribeSystemLiveView success'); 75 }).catch((error: Base.BusinessError) => { 76 console.error(`subscribeSystemLiveView fail: ${JSON.stringify(error)}`); 77 }); 78 console.info(TAG, 'initCapsuleIcon begin'); 79 this.initCapsuleIcon(); 80 console.info(TAG, 'init end'); 81 this.isInit = true; 82 } 83 84 async cancelNotificationById(id: number): Promise<void> { 85 try { 86 await notificationManager.cancel(id, LABEL); 87 console.info(TAG, 'cancel notification success'); 88 } catch (err) { 89 if (err) { 90 console.error(TAG, 'cancel notification err: ' + JSON.stringify(err)); 91 } 92 } 93 } 94 95 sendNotice(): void { 96 console.debug(TAG, 'sendNotice begin==>'); 97 console.debug(TAG, `removalWantAgentObj is ${this.removalWantAgentObj}`); 98 let applicationContext = (GlobalContext.getContext().getObject('appcontext')) as context.ApplicationContext; 99 let resourceManager = applicationContext.resourceManager; 100 let imagePixelMap = resourceManager.getDrawableDescriptor($r('app.media.icon_notice')).getPixelMap(); 101 let capsuleColor = resourceManager.getColorSync($r('sys.color.ohos_id_color_warning')); 102 let title = resourceManager.getStringSync($r('app.string.notice_title')); 103 let text = resourceManager.getStringSync($r('app.string.notice_text')); 104 text = util.format(text, ''); 105 let noticeText = resourceManager.getStringSync($r('app.string.notice_title')); 106 let cancelBnText = resourceManager.getStringSync($r('app.string.bn_notice_cancel')); 107 let cancelBnImage = resourceManager.getDrawableDescriptor($r('app.media.link_slash')).getPixelMap(); 108 let notificationRequest: notificationManager.NotificationRequest = { 109 id: NOTICE_ID, 110 label: LABEL, 111 isOngoing: true, 112 isFloatingIcon: true, 113 smallIcon: imagePixelMap, 114 isUnremovable: false, 115 removalWantAgent: this.removalWantAgentObj, 116 slotType: notificationManager.SlotType.LIVE_VIEW, 117 content: { 118 notificationContentType: notificationManager.ContentType.NOTIFICATION_CONTENT_SYSTEM_LIVE_VIEW, 119 systemLiveView: { 120 title: title, 121 text: text, 122 typeCode: 1, 123 capsule: { 124 title: noticeText, 125 backgroundColor: String(capsuleColor), 126 icon: this.capsuleIcon! 127 128 }, 129 button: { 130 names: [cancelBnText], 131 icons: [cancelBnImage], 132 }, 133 }, 134 }, 135 }; 136 137 console.debug(TAG, `publish content is ${JSON.stringify(notificationRequest)}`); 138 notificationManager.publish(notificationRequest, (err: Base.BusinessError) => { 139 if (err) { 140 console.error(TAG, TAG + `Failed to publish notification. Code is ${err.code}, message is ${err.message}`); 141 return; 142 } 143 console.info(TAG, 'succeeded in publishing notification.'); 144 }); 145 } 146 147 async initRemovalWantAgent(): Promise<void> { 148 console.info(TAG, 'initRemovalWantAgent begin'); 149 if (this.removalWantAgentObj !== null) { 150 console.info(TAG, 'RemovalWantAgent has init'); 151 return; 152 } 153 try { 154 await WantAgent.getWantAgent(this.removalWantAgentInfo).then((data) => { 155 this.removalWantAgentObj = data; 156 console.info(TAG, `initRemovalWantAgent getWantAgent ok`); 157 }).catch((err: Base.BusinessError) => { 158 console.error(TAG, `initRemovalWantAgent getWantAgent failed, code: ${JSON.stringify(err.code)}, message: ${JSON.stringify(err.message)}`); 159 }); 160 } catch (err: Base.BusinessError) { 161 console.error(TAG, `initRemovalWantAgent getWantAgent catch failed, code: ${JSON.stringify(err.code)}, message: ${JSON.stringify(err.message)}`); 162 } 163 console.info(TAG, 'initRemovalWantAgent getWantAgent end'); 164 } 165 166 async cancelAuthorization(): Promise<void> { 167 console.debug(TAG, 'cancelAuthorization begin===>'); 168 try { 169 inputEventClient.permitInjection(false); 170 } catch (err: Base.BusinessError) { 171 console.error(TAG + `cancelAuthorization fail: ${JSON.stringify(err)}`); 172 } 173 console.debug(TAG, 'cancelAuthorization end===>'); 174 } 175 176 createCommonEventSubscriber(): void { 177 console.debug(TAG, 'createCommonEventSubscriber begin===>'); 178 if (this.commonEventSubscriber !== null) { 179 console.debug(TAG, `commonEventSubscriber has init`); 180 return; 181 } 182 let subscribeInfo: CommonEventManager.CommonEventSubscribeInfo = { 183 events: [EVENT_NAME], 184 publisherPermission: 'ohos.permission.INJECT_INPUT_EVENT', 185 }; 186 CommonEventManager.createSubscriber(subscribeInfo).then((commonEventSubscriber: CommonEventManager.CommonEventSubscriber) => { 187 console.debug(TAG, 'createCommonEventSubscriber ok'); 188 this.commonEventSubscriber = commonEventSubscriber; 189 this.subscribe(); 190 }).catch((err: Base.BusinessError) => { 191 console.error(TAG, `createCommonEventSubscriber fail:${JSON.stringify(err)}}`); 192 }); 193 console.debug(TAG, 'cancelAuthorization end'); 194 } 195 196 subscribe(): void { 197 console.debug(TAG, 'subscribe begin'); 198 if (this.commonEventSubscriber === null) { 199 console.debug(TAG, 'subscribe commonEventSubscriber is null'); 200 return; 201 } 202 CommonEventManager.subscribe(this.commonEventSubscriber, (err: Base.BusinessError, 203 data: CommonEventManager.CommonEventData) => { 204 if (err.code) { 205 console.error(TAG, `commonEventSubscribeCallBack err:${JSON.stringify(err)}`); 206 return; 207 } 208 console.error(TAG, `commonEventSubscribeCallBack data:${JSON.stringify(data)}`); 209 let code: number = data.code; 210 if (code !== 0) { 211 console.error(TAG, 'commonEventSubscribeCallBack !==0'); 212 return; 213 } 214 if ('noticeId' in data.parameters) { 215 console.debug(TAG, `commonEventSubscribeCallBack data noticeId has value`); 216 if (data.parameters.noticeId === NOTICE_ID) { 217 console.debug(TAG, `commonEventSubscribeCallBack data event: ${data.event} close notice`); 218 injectNoticeUtil.cancelAuthorization(); 219 injectNoticeUtil.cancelNotificationById(NOTICE_ID); 220 return; 221 } 222 } 223 }); 224 console.debug(TAG, 'subscribe end'); 225 } 226 227 onSystemLiveBttonsResponse(notificationId: number, 228 buttonOptions: notificationManager.ButtonOptions): void { 229 console.debug(TAG, 'onSystemLiveBttonsResponse:', JSON.stringify(buttonOptions), 'id:' + notificationId); 230 } 231 232 onLiveNoticeResponseCallback(notificationId: number, buttonOptions: notificationManager.ButtonOptions): void { 233 console.debug(TAG, 'onLiveNoticeResponseCallback enter'); 234 if (buttonOptions == null) { 235 console.error(TAG, 'onLiveNoticeResponseCallback button callback: ' + 'buttonOptions is null'); 236 return; 237 } 238 let clickButtonName = buttonOptions.buttonName; 239 let applicationContext = (GlobalContext.getContext().getObject('appcontext')) as context.ApplicationContext; 240 let resourceManager = applicationContext.resourceManager; 241 let locateButtonName = resourceManager.getStringSync($r('app.string.bn_notice_cancel')); 242 console.info(TAG, 'onLiveNoticeResponseCallback button callback: ' + clickButtonName + ', notificationId = ' + notificationId); 243 if (clickButtonName === locateButtonName) { 244 console.debug(TAG, `onLiveNoticeResponseCallback close notice`); 245 injectNoticeUtil.cancelAuthorization(); 246 injectNoticeUtil.cancelNotificationById(NOTICE_ID); 247 } 248 } 249 250 async initCapsuleIcon(): Promise<void> { 251 console.debug(TAG, `initCapsuleIcon begin`); 252 if (this.capsuleIcon != null) { 253 console.debug(TAG, `initCapsuleIcon has init`); 254 return; 255 } 256 let applicationContext = (GlobalContext.getContext().getObject('appcontext')) as context.ApplicationContext; 257 let resourceManager = applicationContext.resourceManager; 258 let defaultSize: image.Size = { 259 'height': 30, 260 'width': 30, 261 }; 262 let svgData = resourceManager.getMediaContentSync($r('app.media.capsule_icon34')); 263 let opts: image.DecodingOptions = { 264 'index': 0, 265 'sampleSize': 1, 266 'rotate' :0, 267 'editable': true, 268 'desiredSize': defaultSize, 269 'desiredPixelFormat': 3, 270 }; 271 let imageSource = image.createImageSource(svgData.buffer); 272 let svImage: image.PixelMap | null = null; 273 svImage = await imageSource.createPixelMap(opts); 274 this.capsuleIcon = svImage; 275 console.debug(TAG, `initCapsuleIcon end vaule: ${this.capsuleIcon}`); 276 } 277} 278 279export let injectNoticeUtil = new InjectNoticeUtil();