1/* 2 * Copyright (c) 2023 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 router from '@ohos.router'; 17import fs from '@ohos.file.fs'; 18import common from '@ohos.app.ability.common'; 19import picker from '@ohos.file.picker'; 20import photoAccessHelper from '@ohos.file.photoAccessHelper'; 21import image from '@ohos.multimedia.image'; 22import Logger from '../utils/Logger'; 23import CommonConstants from '../common/constants/CommonConstants'; 24import { BusinessError } from '@ohos.base'; 25import { LooperUtil } from '../utils/LooperUtil'; 26 27const TAG = 'testTag_Notes: '; 28let context = getContext(this) as common.UIAbilityContext; //获取设备A&B UIAbilityContext信息 29let disPath: string = context.distributedFilesDir; 30//获取分布式目录的文件路径 31let filePath: string = disPath + '/picture.jpg'; 32 33@Entry 34@Component 35struct Notes { 36 @State text: string = ''; 37 @State img: string = 'app.media.pic_image'; 38 @StorageLink('isContinuation') isContinuation: boolean = false; 39 @StorageLink('isSelectImg') isSelectImg: boolean = false; 40 @StorageLink('inputText') inputText: string = ''; 41 @StorageLink('inputTextArea') inputTextArea: string = ''; 42 @StorageLink('imgStr') imgStr: string = 'app.media.pic_image'; 43 @StorageLink('ability_isON') stoLink_ability_isON: boolean = true; 44 controller: TextAreaController = new TextAreaController(); 45 @State num: number = 0; 46 @State image2: Object = new Object; // 图二展示照片(选择或流转) 47 @StorageLink('imgIsVisible1') imgIsVisible1: boolean = true; 48 @StorageLink('imgIsVisible2') imgIsVisible2: boolean = true; 49 @State showSubMenus: boolean = false; 50 @State jpgStr: string = ''; 51 @State uris2: Array<string> = []; // 用于接受 PhotoViewPicker选择图片2的返回的uri(分布式对象方式) 52 @State fileName: string = ''; 53 @State readLenAtSink: number = 0; 54 private imgArray: Resource[] = [ 55 $r('app.media.pic_image'), 56 $r('app.media.img_08'), 57 $r('app.media.img_07') 58 ] 59 60 choosePictureFileForImage2(): void { 61 try { 62 let photoSelectOptions = new picker.PhotoSelectOptions(); 63 photoSelectOptions.MIMEType = picker.PhotoViewMIMETypes.IMAGE_TYPE; 64 photoSelectOptions.maxSelectNumber = 1; 65 let photoPicker = new picker.PhotoViewPicker(); 66 photoPicker.select(photoSelectOptions).then((photoSelectResult) => { 67 if (!photoSelectResult) { 68 Logger.error(TAG, 'choosePicture2 photoSelectResult = null'); 69 return; 70 } 71 this.uris2 = photoSelectResult.photoUris; 72 73 if (this.writeDistributedAsset()) { 74 Logger.info(TAG, "choosePicture2 success"); 75 } else { 76 Logger.error(TAG, 'choosePicture2 failed'); 77 } 78 79 // 获取图库中清晰图片PixelMap 80 // 1.通过uri打开文件得到fd 81 let file = fs.openSync(this.uris2[0], fs.OpenMode.READ_ONLY); 82 // 2.通过imageSourceApi来创建pixelMap并直接显示 83 let imageSourceApi = image.createImageSource(file.fd); 84 if (imageSourceApi) { 85 imageSourceApi.createPixelMap().then((pixelMap) => { 86 this.image2 = pixelMap; 87 this.imgIsVisible2 = false; 88 }); 89 AppStorage.setOrCreate<string>('image2Path', CommonConstants.DISTRIBUTED_ASSET_SAVE_PATH); 90 } else { 91 Logger.info(TAG, 'choosePicture2 imageSourceApi is undefined'); 92 } 93 }) 94 } catch (error) { 95 Logger.error(TAG, 'choosePicture2 photoPicker failed with error: ' + JSON.stringify(error)); 96 } 97 } 98 99 writeDistributedAsset(): boolean { 100 Logger.info(TAG, 'writeDistributedAsset in'); 101 // 删除目录 102 try { 103 fs.rmdirSync(CommonConstants.DISTRIBUTED_ASSET_DIR); 104 Logger.info(TAG, 'remove dir successful'); 105 } catch (error) { 106 Logger.info(TAG, `remove dir failed, cause: ${JSON.stringify(error)}`); 107 } 108 try { 109 fs.mkdirSync(CommonConstants.DISTRIBUTED_ASSET_DIR, true); 110 let srcFile = fs.openSync(this.uris2[0], fs.OpenMode.READ_ONLY); 111 let dstFile = fs.openSync(CommonConstants.DISTRIBUTED_ASSET_SAVE_PATH, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE); 112 Logger.info(TAG, 'writeDistributedAsset open srcFile dstFile success!'); 113 const bufSize = 4096; 114 let readSize = 0; 115 let buf = new ArrayBuffer(bufSize); 116 let readLen = fs.readSync(srcFile.fd as number, buf, { offset: readSize }); 117 while (readLen > 0) { 118 readSize += readLen; 119 fs.writeSync(dstFile.fd as number, buf, { length: readLen }); 120 readLen = fs.readSync(srcFile.fd as number, buf, { offset: readSize }); 121 } 122 Logger.info(TAG, 'copy file success size: ' + readSize); 123 fs.close(srcFile); 124 fs.close(dstFile); 125 return true; 126 } catch (error) { 127 Logger.error(TAG, `writeDistributedAsset error, cause: ${JSON.stringify(error)}`); 128 } 129 return false; 130 } 131 132 readDistributedAsset(): void { 133 Logger.info(TAG, 'readDistributedAsset in'); 134 try { 135 let image2Path = AppStorage.get<string>('image2Path'); 136 if (image2Path == undefined || image2Path == '') { 137 Logger.info(TAG, `image2Path error, cause: $JSON.stringify(image2Path)`); 138 return; 139 } 140 if (fs.accessSync(image2Path)) { 141 Logger.info(TAG, 'open distributed asset successfully'); 142 } else { 143 Logger.error(TAG, 'distributed asset does not exists'); 144 return; 145 } 146 let imageSource = image.createImageSource(image2Path); 147 imageSource.createPixelMap().then((pixelMap) => { 148 Logger.info(TAG, 'createPixelMap successfully') 149 this.image2 = pixelMap; 150 this.imgIsVisible2 = false; 151 }) 152 Logger.info(TAG, 'readDistributedAsset successfully'); 153 } catch (error) { 154 Logger.error(TAG, `readDistributedAsset error, cause: ${JSON.stringify(error)}`); 155 } 156 } 157 158 aboutToAppear() { 159 Logger.info(TAG, 'aboutToAppear in'); 160 LooperUtil.on(CommonConstants.EVENT_DATA_RESTORE, () => { 161 this.readDistributedAsset(); 162 }); 163 } 164 165 aboutToDisappear(): void { 166 Logger.info(TAG, 'aboutToDisappear in'); 167 LooperUtil.off(CommonConstants.EVENT_DATA_RESTORE); 168 AppStorage.set<string>('image2Path', ''); 169 this.isSelectImg = false; 170 this.imgIsVisible1 = true; 171 this.imgIsVisible2 = true; 172 } 173 174 build() { 175 Row() { 176 Column() { 177 Column() { 178 179 // 顶部导航 180 Flex({ direction: FlexDirection.Row }) { 181 Row() { 182 Image($r('app.media.ic_back')) 183 .width(24) 184 .height(24) 185 .margin({ right: 16 }) 186 .id('back_arrow_notes') 187 188 } 189 .width(30) 190 .height(30) 191 .onClick(() => { 192 router.back() 193 }) 194 195 Text(CommonConstants.NOTES_TITLE) 196 .fontSize(20) 197 .fontWeight(500) 198 .margin({ top: 5, left: 16 }) 199 200 } 201 .margin({ top: 36, left: 24, bottom: 14 }) 202 .width(360) 203 204 Column() { 205 206 TextInput({ text: this.inputText, 207 placeholder: CommonConstants.PLEASE_INPUT_NOTE_TITLE 208 }) 209 .fontWeight(500) 210 .fontSize(30) 211 .textAlign(TextAlign.JUSTIFY) 212 .align(Alignment.Center) 213 .height(51) 214 .onChange((value: string) => { 215 this.inputText = value; 216 AppStorage.set('inputText', value); 217 Logger.info(TAG, 'this.inputText: ' + this.inputText); 218 }) 219 .type(InputType.Normal) 220 .backgroundColor(Color.Transparent) 221 .margin({ left: -14 }) 222 .restoreId(2) 223 .id('textInput') 224 225 226 Text(CommonConstants.NOTES_TIME) 227 .fontWeight(400) 228 .fontSize(14) 229 .textAlign(TextAlign.JUSTIFY) 230 .fontColor('#182431') 231 .lineHeight(19) 232 233 TextArea({ 234 text: this.inputTextArea, 235 placeholder: CommonConstants.PLEASE_INPUT_NOTE_CONTENT, 236 controller: this.controller 237 }) 238 .placeholderFont({ size: 16, weight: 400 }) 239 .placeholderColor('#182431') 240 .width('100%') 241 .height(126) 242 .margin({ top: 16 }) 243 .fontSize(16) 244 .fontColor('#182431') 245 .backgroundColor('#FFFFFF') 246 .onChange((value: string) => { 247 this.inputTextArea = value; 248 AppStorage.set('inputTextArea', value); 249 }) 250 .restoreId(3) 251 .id('textArea') 252 253 // 分布式对象携带附件: 迁移图片 254 Row() { 255 // 初始站位小图 256 Image(this.imgArray[0]) 257 .width(48) 258 .height(48) 259 .margin({ left: 144 }) 260 .visibility(this.imgIsVisible2 ? Visibility.Visible : Visibility.None) 261 // 大图 262 Image(this.image2 as PixelMap) 263 .width('100%') 264 .height('100%') 265 .borderRadius(24) 266 .syncLoad(true) 267 .onComplete((msg) => { 268 Logger.info(TAG, 'load image success 03'); 269 })// 图片获取失败打印结果 270 .onError(() => { 271 Logger.info(TAG, 'load image fail 03') 272 }) 273 .visibility(this.imgIsVisible2 ? Visibility.None : Visibility.Visible) 274 } 275 .width('100%') 276 .height(154) 277 .backgroundColor('#FFFFFF') 278 .borderRadius(24) 279 .margin({ top: 12 }) 280 281 Text($r('app.string.PICTURE_TWO')) 282 .fontSize(12) 283 .fontColor('#182431') 284 .height(16) 285 .fontWeight(500) 286 .margin({ top: 8, left: 152, bottom: 32 }) 287 288 Flex({ alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) { 289 290 Button($r('app.string.pick_photo_two'), { type: ButtonType.Capsule, stateEffect: true }) 291 .backgroundColor('rgba(24,36,49,0.05)') 292 .width(150) 293 .height(40) 294 .fontColor('#007DFF') 295 .onClick(() => { 296 this.choosePictureFileForImage2(); 297 }) 298 .id('button_select_picture_two') 299 300 } 301 } 302 .width(336) 303 .alignItems(HorizontalAlign.Start) 304 } 305 .width(360) 306 .alignItems(HorizontalAlign.Center) 307 } 308 .width('100%') 309 .height('100%') 310 } 311 .width('100%') 312 .height('100%') 313 .alignItems(VerticalAlign.Top) 314 .backgroundColor('#f1f3f5') 315 } 316}