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.app.ability.wantAgent'; 20import CommonEventManager from '@ohos.commonEventManager'; 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 InjectNoticeStatus { 32 DEFAULT = 0, 33 OPENING = 1, 34 SERVER_CLOSE = 2, 35 MAN_CLOSE = 3, 36}; 37 38class InjectNoticeUtil { 39 status: InjectNoticeStatus = InjectNoticeStatus.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 actionType: WantAgent.OperationType.SEND_COMMON_EVENT, 53 requestCode: 0, 54 actionFlags: [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 notificationSlotType: 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 (error) { 161 let err = error as Base.BusinessError; 162 console.error(TAG, `initRemovalWantAgent getWantAgent catch failed, code: ${JSON.stringify(err.code)}, message: ${JSON.stringify(err.message)}`); 163 } 164 console.info(TAG, 'initRemovalWantAgent getWantAgent end'); 165 } 166 167 async cancelAuthorization(): Promise<void> { 168 console.debug(TAG, 'cancelAuthorization begin===>'); 169 try { 170 inputEventClient.permitInjection(false); 171 } catch (error) { 172 let err = error as Base.BusinessError; 173 console.error(TAG + `cancelAuthorization fail: ${JSON.stringify(err)}`); 174 } 175 console.debug(TAG, 'cancelAuthorization end===>'); 176 } 177 178 createCommonEventSubscriber(): void { 179 console.debug(TAG, 'createCommonEventSubscriber begin===>'); 180 if (this.commonEventSubscriber !== null) { 181 console.debug(TAG, `commonEventSubscriber has init`); 182 return; 183 } 184 let subscribeInfo: CommonEventManager.CommonEventSubscribeInfo = { 185 events: [EVENT_NAME], 186 publisherPermission: 'ohos.permission.INJECT_INPUT_EVENT', 187 }; 188 CommonEventManager.createSubscriber(subscribeInfo).then((commonEventSubscriber: CommonEventManager.CommonEventSubscriber) => { 189 console.debug(TAG, 'createCommonEventSubscriber ok'); 190 this.commonEventSubscriber = commonEventSubscriber; 191 this.subscribe(); 192 }).catch((err: Base.BusinessError) => { 193 console.error(TAG, `createCommonEventSubscriber fail:${JSON.stringify(err)}}`); 194 }); 195 console.debug(TAG, 'cancelAuthorization end'); 196 } 197 198 subscribe(): void { 199 console.debug(TAG, 'subscribe begin'); 200 if (this.commonEventSubscriber === null) { 201 console.debug(TAG, 'subscribe commonEventSubscriber is null'); 202 return; 203 } 204 CommonEventManager.subscribe(this.commonEventSubscriber, (err: Base.BusinessError, 205 data: CommonEventManager.CommonEventData) => { 206 if (err.code) { 207 console.error(TAG, `commonEventSubscribeCallBack err:${JSON.stringify(err)}`); 208 return; 209 } 210 console.error(TAG, `commonEventSubscribeCallBack data:${JSON.stringify(data)}`); 211 let code: number = data.code; 212 if (code !== 0) { 213 console.error(TAG, 'commonEventSubscribeCallBack !==0'); 214 return; 215 } 216 if ('noticeId' in data.parameters) { 217 console.debug(TAG, `commonEventSubscribeCallBack data noticeId has value`); 218 if (data.parameters.noticeId === NOTICE_ID) { 219 console.debug(TAG, `commonEventSubscribeCallBack data event: ${data.event} close notice`); 220 injectNoticeUtil.cancelAuthorization(); 221 injectNoticeUtil.cancelNotificationById(NOTICE_ID); 222 return; 223 } 224 } 225 }); 226 console.debug(TAG, 'subscribe end'); 227 } 228 229 onSystemLiveBttonsResponse(notificationId: number, 230 buttonOptions: notificationManager.ButtonOptions): void { 231 console.debug(TAG, 'onSystemLiveBttonsResponse:', JSON.stringify(buttonOptions), 'id:' + notificationId); 232 } 233 234 onLiveNoticeResponseCallback(notificationId: number, buttonOptions: notificationManager.ButtonOptions): void { 235 console.debug(TAG, 'onLiveNoticeResponseCallback enter'); 236 if (buttonOptions == null) { 237 console.error(TAG, 'onLiveNoticeResponseCallback button callback: ' + 'buttonOptions is null'); 238 return; 239 } 240 let clickButtonName = buttonOptions.buttonName; 241 let applicationContext = (GlobalContext.getContext().getObject('appcontext')) as context.ApplicationContext; 242 let resourceManager = applicationContext.resourceManager; 243 let locateButtonName = resourceManager.getStringSync($r('app.string.bn_notice_cancel')); 244 console.info(TAG, 'onLiveNoticeResponseCallback button callback: ' + clickButtonName + ', notificationId = ' + notificationId); 245 if (clickButtonName === locateButtonName) { 246 console.debug(TAG, `onLiveNoticeResponseCallback close notice`); 247 injectNoticeUtil.cancelAuthorization(); 248 injectNoticeUtil.cancelNotificationById(NOTICE_ID); 249 } 250 } 251 252 async initCapsuleIcon(): Promise<void> { 253 console.debug(TAG, `initCapsuleIcon begin`); 254 if (this.capsuleIcon != null) { 255 console.debug(TAG, `initCapsuleIcon has init`); 256 return; 257 } 258 let applicationContext = (GlobalContext.getContext().getObject('appcontext')) as context.ApplicationContext; 259 let resourceManager = applicationContext.resourceManager; 260 let defaultSize: image.Size = { 261 'height': 30, 262 'width': 30, 263 }; 264 let svgData = resourceManager.getMediaContentSync($r('app.media.capsule_icon34')); 265 let opts: image.DecodingOptions = { 266 'index': 0, 267 'sampleSize': 1, 268 'rotate' :0, 269 'editable': true, 270 'desiredSize': defaultSize, 271 'desiredPixelFormat': 3, 272 }; 273 let imageSource = image.createImageSource(svgData.buffer); 274 let svImage: image.PixelMap | null = null; 275 svImage = await imageSource.createPixelMap(opts); 276 this.capsuleIcon = svImage; 277 console.debug(TAG, `initCapsuleIcon end vaule: ${this.capsuleIcon}`); 278 } 279} 280 281export let injectNoticeUtil = new InjectNoticeUtil();