From 1b5aea1138251db4ee8ddcb90d14cfcfcc8bb8cc Mon Sep 17 00:00:00 2001 From: zhoulisheng1 Date: Thu, 16 Mar 2023 17:39:59 +0800 Subject: [PATCH 1/2] =?UTF-8?q?1.=E6=96=B0=E5=A2=9E=E5=8A=9F=E8=83=BD:?= =?UTF-8?q?=E6=94=AF=E6=8C=81=E8=87=AA=E5=AE=9A=E4=B9=89=E7=BC=93=E5=AD=98?= =?UTF-8?q?key=202.=E6=B7=BB=E5=8A=A0=E7=BC=93=E5=AD=98key=E4=B8=AD?= =?UTF-8?q?=E7=9A=84url=E9=9C=80=E8=A6=81=E5=89=94=E9=99=A4token=E7=9A=84?= =?UTF-8?q?=E6=BC=94=E7=A4=BA=E7=95=8C=E9=9D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zhoulisheng1 --- .../ets/entryability/CustomEngineKeyImpl.ets | 63 ++++++++++++++++ .../src/main/ets/entryability/EntryAbility.ts | 5 +- ...tCasePage.ets => CacheRuleChangedPage.ets} | 53 ++++++++++---- .../ets/pages/imageknifeTestCaseIndex.ets | 8 +-- .../resources/base/profile/main_pages.json | 2 +- imageknife/index.ets | 2 + .../ets/components/cache/key/EngineKey.ets | 72 ++++++------------- .../cache/key/EngineKeyFactories.ets | 39 ++++++---- .../cache/key/EngineKeyInterface.ets | 27 +++++++ .../ets/components/imageknife/ImageKnife.ets | 48 +++++++++++-- package.json | 2 + 11 files changed, 234 insertions(+), 87 deletions(-) create mode 100644 entry/src/main/ets/entryability/CustomEngineKeyImpl.ets rename entry/src/main/ets/pages/{frescoImageTestCasePage.ets => CacheRuleChangedPage.ets} (55%) create mode 100644 imageknife/src/main/ets/components/cache/key/EngineKeyInterface.ets diff --git a/entry/src/main/ets/entryability/CustomEngineKeyImpl.ets b/entry/src/main/ets/entryability/CustomEngineKeyImpl.ets new file mode 100644 index 0000000..a89aba9 --- /dev/null +++ b/entry/src/main/ets/entryability/CustomEngineKeyImpl.ets @@ -0,0 +1,63 @@ +import { EngineKeyInterface,EngineKeyFactories, RequestOption } from '@ohos/imageknife' + +export class CustomEngineKeyImpl implements EngineKeyInterface { + + redefineUrl:(loadSrc:string)=>string; + + addOtherInfo:string = "Version=1.0.0;" + + constructor() { + this.redefineUrl = this.urlNeedClearToken.bind(this); + } + // request只读 + generateMemoryCacheKey(loadSrc:string,size:string,transformed:string,dontAnimate:boolean):string { + return EngineKeyFactories.createMemoryCacheKey(loadSrc,size,transformed,dontAnimate,this.redefineUrl,this.addOtherInfo); + } + + generateTransformedDiskCacheKey(loadSrc:string,size:string,transformed:string,dontAnimate:boolean):string { + return EngineKeyFactories.createTransformedDiskCacheKey(loadSrc,size,transformed,dontAnimate,this.redefineUrl,this.addOtherInfo); + } + + generateOriginalDiskCacheKey(loadSrc:string):string { + return EngineKeyFactories.createOriginalDiskCacheKey(loadSrc,this.redefineUrl,this.addOtherInfo); + } + + + // 需求场景: 请求图片可能 请求中存在token需要清除, 可以把输入的url清除token后作为key的一部分,这样token发生变化也能命中缓存。 + urlNeedClearToken(url:string):string { + if (this.isHttpRequest(url)) { + return this.clearToken(url) + } else { + return url; + } + } + + + isHttpRequest(loadSrc:string){ + if(typeof loadSrc == "string" && loadSrc.toLowerCase().startsWith("http")){ + return true; + } + return false; + } + + // 清除url里面中携带的token + clearToken(url:string):string{ + let retUrl = url.replace(this.findTokenParam(url),"") + return retUrl; + } + + // 网络图片加载 可能因为Token问题导致缓存失效 + findTokenParam(url: string): string { + let tokenParam = ""; + let tokenKeyIndex = url.indexOf("?token=") >= 0 ? url.indexOf("?token=") : url.indexOf("&token="); + if (tokenKeyIndex != -1) { + let nextAndIndex = url.indexOf("&", tokenKeyIndex + 1); + if (nextAndIndex != -1) { + tokenParam = url.substring(tokenKeyIndex + 1, nextAndIndex + 1); + } else { + tokenParam = url.substring(tokenKeyIndex); + } + } + return tokenParam; + } +} diff --git a/entry/src/main/ets/entryability/EntryAbility.ts b/entry/src/main/ets/entryability/EntryAbility.ts index 2243e00..5589925 100644 --- a/entry/src/main/ets/entryability/EntryAbility.ts +++ b/entry/src/main/ets/entryability/EntryAbility.ts @@ -1,7 +1,8 @@ import UIAbility from '@ohos.app.ability.UIAbility'; import hilog from '@ohos.hilog'; import window from '@ohos.window'; -import { ImageKnife,ImageKnifeDrawFactory} from '@ohos/imageknife' +import { ImageKnife,ImageKnifeDrawFactory } from '@ohos/imageknife' +import { CustomEngineKeyImpl } from './CustomEngineKeyImpl' export default class EntryAbility extends UIAbility { onCreate(want, launchParam) { @@ -9,6 +10,8 @@ export default class EntryAbility extends UIAbility { globalThis.ImageKnife = ImageKnife.with(this.context); // 全局配置网络加载进度条 globalThis.ImageKnife.setDefaultLifeCycle(ImageKnifeDrawFactory.createProgressLifeCycle("#10a5ff", 0.5)) + // 全局配置缓存key + globalThis.ImageKnife.setEngineKeyImpl(new CustomEngineKeyImpl()) } onDestroy() { diff --git a/entry/src/main/ets/pages/frescoImageTestCasePage.ets b/entry/src/main/ets/pages/CacheRuleChangedPage.ets similarity index 55% rename from entry/src/main/ets/pages/frescoImageTestCasePage.ets rename to entry/src/main/ets/pages/CacheRuleChangedPage.ets index c12ee29..aac53dd 100644 --- a/entry/src/main/ets/pages/frescoImageTestCasePage.ets +++ b/entry/src/main/ets/pages/CacheRuleChangedPage.ets @@ -12,16 +12,17 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import {ImageKnifeComponent} from '@ohos/imageknife' -import {ImageKnifeOption} from '@ohos/imageknife' -import {RotateImageTransformation} from '@ohos/imageknife' -import {RoundedCornersTransformation} from '@ohos/imageknife' +import { + ImageKnifeComponent, + ImageKnifeOption, + RotateImageTransformation, + RoundedCornersTransformation +} from '@ohos/imageknife' @Entry @Component -struct FrescoImageTestCasePage { - - @State progresshint:string = "输出加载百分比回调信息" +struct CacheRuleChangedPage { + @State progresshint: string = "输出加载百分比回调信息" @State imageKnifeOption1: ImageKnifeOption = { loadSrc: "https://thirdwx.qlogo.cn/mmopen/vi_32/DYAIOgq83ericA1Mv66TwicuYOtbDMBcUhv1aa9RJBeAn9uURfcZD0AUGrJebAn1g2AjN0vb2E1XTET7fTuLBNmA/132", @@ -50,6 +51,14 @@ struct FrescoImageTestCasePage { { loadSrc: "https://hbimg.huabanimg.com/cc6af25f8d782d3cf3122bef4e61571378271145735e9-vEVggB", + placeholderSrc: $r('app.media.icon_loading'), + errorholderSrc: $r('app.media.icon_failed'), + displayProgress: true, + }; + @State imageKnifeOption5: ImageKnifeOption = + { + loadSrc: "https://hbimg.huabanimg.com/95a6d37a39aa0b70d48fa18dc7df8309e2e0e8e85571e-x4hhks_fw658/format/webp?mama=sdafsfasdfsdfsdaf&baba=sdfsafsafsd", + placeholderSrc: $r('app.media.icon_loading'), errorholderSrc: $r('app.media.icon_failed'), displayProgress: true, @@ -58,17 +67,35 @@ struct FrescoImageTestCasePage { build() { Scroll() { Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) { -// ImageKnifeComponent({ imageKnifeOption: this.imageKnifeOption1 }) -// ImageKnifeComponent({ imageKnifeOption: this.imageKnifeOption }) -// ImageKnifeComponent({ imageKnifeOption: this.imageKnifeOption3 }) + + Text('下图默认加载网络图片不带?token=').margin({top:20}) + Button('点击加载网络图片?token=').margin({top:5}).onClick(() => { + + this.imageKnifeOption4 = { + loadSrc: "https://hbimg.huabanimg.com/cc6af25f8d782d3cf3122bef4e61571378271145735e9-vEVggB?token=fsdafsfsafsafsdaf111111", + placeholderSrc: $r('app.media.icon_loading'), + errorholderSrc: $r('app.media.icon_failed'), + displayProgress: true, + } + }) + ImageKnifeComponent({ imageKnifeOption: this.imageKnifeOption4 }) .width(300) .height(300) -// Scroll() { -// Text(this.progresshint).fontSize(15) -// }.width(300).height(200) + Text('下图默认加载网络图片不带&token=').margin({top:20}) + Button('点击加载网络图片&token=').margin({top:5}).onClick(() => { + this.imageKnifeOption5 = { + loadSrc: "https://hbimg.huabanimg.com/95a6d37a39aa0b70d48fa18dc7df8309e2e0e8e85571e-x4hhks_fw658/format/webp?mama=sdafsfasdfsdfsdaf&token=fsdafsfsafsafsdaf111111&baba=sdfsafsafsd", + placeholderSrc: $r('app.media.icon_loading'), + errorholderSrc: $r('app.media.icon_failed'), + displayProgress: true, + } + }) + ImageKnifeComponent({ imageKnifeOption: this.imageKnifeOption5 }) + .width(300) + .height(300) } } .width('100%') diff --git a/entry/src/main/ets/pages/imageknifeTestCaseIndex.ets b/entry/src/main/ets/pages/imageknifeTestCaseIndex.ets index 108abb5..f01d186 100644 --- a/entry/src/main/ets/pages/imageknifeTestCaseIndex.ets +++ b/entry/src/main/ets/pages/imageknifeTestCaseIndex.ets @@ -127,12 +127,12 @@ struct IndexFunctionDemo { }).margin({ top: 5, left: 3 }) }.width('100%').height(60).backgroundColor(Color.Pink) - Text("测试fresco").fontSize(15) + Text("测试缓存规则和重试").fontSize(15) Flex({ direction: FlexDirection.Row, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) { - Button("加载百分比") + Button("更改缓存规则") .onClick(() => { - console.log("加载百分比") - router.push({ uri: "pages/frescoImageTestCasePage" }); + console.log("更改缓存规则") + router.push({ uri: "pages/CacheRuleChangedPage" }); }).margin({ top: 5, left: 3 }) Button("重试Retry") .onClick(() => { diff --git a/entry/src/main/resources/base/profile/main_pages.json b/entry/src/main/resources/base/profile/main_pages.json index 37dfa72..1d45314 100644 --- a/entry/src/main/resources/base/profile/main_pages.json +++ b/entry/src/main/resources/base/profile/main_pages.json @@ -1,7 +1,7 @@ { "src": [ "pages/index", - "pages/frescoImageTestCasePage", + "pages/CacheRuleChangedPage", "pages/frescoRetryTestCasePage", "pages/basicTestFeatureAbilityPage", "pages/basicTestFileIOPage", diff --git a/imageknife/index.ets b/imageknife/index.ets index b37f483..c4e36ac 100644 --- a/imageknife/index.ets +++ b/imageknife/index.ets @@ -27,6 +27,8 @@ export * from './src/main/ets/components/cache/diskstrategy/enum/AUTOMATIC' export * from './src/main/ets/components/cache/diskstrategy/enum/DATA' export * from './src/main/ets/components/cache/diskstrategy/enum/NONE' export * from './src/main/ets/components/cache/diskstrategy/enum/RESOURCE' +export * from './src/main/ets/components/cache/key/EngineKeyInterface' +export * from './src/main/ets/components/cache/key/EngineKeyFactories' /** * compress diff --git a/imageknife/src/main/ets/components/cache/key/EngineKey.ets b/imageknife/src/main/ets/components/cache/key/EngineKey.ets index be28a7c..1dce528 100644 --- a/imageknife/src/main/ets/components/cache/key/EngineKey.ets +++ b/imageknife/src/main/ets/components/cache/key/EngineKey.ets @@ -17,76 +17,50 @@ import {RequestOption} from '../../imageknife/RequestOption' import {BaseTransform} from '../../imageknife/transform/BaseTransform' export class EngineKey implements Key { - private request: RequestOption; - - constructor( - request - ) { - this.request = request; - } // 内存缓存 缓存生成规则:是否会影响图片内容,不影响则通用(strategy onlyRetrieveFromCache isCacheable)为通用项目 // 生成规则 加载数据原 各类参数(排除监听 排除 占位图 失败占位图) - generateCacheKey(): string{ + public static generateMemoryCacheKey(loadSrc:string,size:string,transformed:string,dontAnimate:boolean, redefine?:(loadSrc:string)=>string, otherInfo?:string): string{ - let loadSrc = JSON.stringify(this.request.loadSrc); - - let size = JSON.stringify(this.request.size); - - let transformationsStr; - if(this.request && this.request.transformations) { - for (let i = 0; i < this.request.transformations.length; i++) { - if (i == this.request.transformations.length - 1) { - transformationsStr += this.request.transformations[i].getName() + ""; - } else { - transformationsStr += this.request.transformations[i].getName() + ","; - } - } + if(redefine){ + loadSrc = redefine(loadSrc); } - let dontAnimateFlag = JSON.stringify(this.request.dontAnimateFlag); - let key = "loadSrc=" + loadSrc + ";" + "size=" + size + ";" + - "transformations=" + transformationsStr + ";" + - "dontAnimateFlag=" + dontAnimateFlag + ";" - + "transformations=" + transformed + ";" + + "dontAnimateFlag=" + dontAnimate + ";" + if(otherInfo){ + key += otherInfo; + } return key; } // 磁盘缓存 缓存生成规则:是否会影响图片内容,不影响则通用(strategy onlyRetrieveFromCache isCacheable)为通用项目 // 生成规则 加载数据原 各类参数(排除监听 排除 占位图 失败占位图) - generateResourceKey(): string{ - - let loadSrc = JSON.stringify(this.request.loadSrc); - - let size = JSON.stringify(this.request.size); - - let transformationsStr; - if(this.request && this.request.transformations) { - for (let i = 0; i < this.request.transformations.length; i++) { - if (i == this.request.transformations.length - 1) { - transformationsStr += this.request.transformations[i].getName() + ""; - } else { - transformationsStr += this.request.transformations[i].getName() + ","; - } - } + public static generateTransformedDiskCacheKey(loadSrc:string,size:string,transformed:string,dontAnimate:boolean, redefine?:(loadSrc:string)=>string, otherInfo?:string): string{ + if(redefine){ + loadSrc = redefine(loadSrc); } - - let dontAnimateFlag = JSON.stringify(this.request.dontAnimateFlag); - let key = "loadSrc=" + loadSrc + ";" + "size=" + size + ";" + - "transformations=" + transformationsStr + ";" + - "dontAnimateFlag=" + dontAnimateFlag + ";" - + "transformations=" + transformed + ";" + + "dontAnimateFlag=" + dontAnimate + ";" + if(otherInfo){ + key += otherInfo; + } return key; } // 磁盘缓存 // 生成网络加载数据 原始数据存于磁盘的key - generateDataKey(): string{ - let loadSrc = JSON.stringify(this.request.loadSrc); + public static generateOriginalDiskCacheKey(loadSrc:string, redefine?:(loadSrc:string)=>string, otherInfo?:string): string{ + if(redefine){ + loadSrc = redefine(loadSrc); + } let key = "loadSrc=" + loadSrc + ";" + if(otherInfo){ + key += otherInfo; + } return key; } diff --git a/imageknife/src/main/ets/components/cache/key/EngineKeyFactories.ets b/imageknife/src/main/ets/components/cache/key/EngineKeyFactories.ets index f81f0ce..1b30570 100644 --- a/imageknife/src/main/ets/components/cache/key/EngineKeyFactories.ets +++ b/imageknife/src/main/ets/components/cache/key/EngineKeyFactories.ets @@ -13,24 +13,39 @@ * limitations under the License. */ import {EngineKey} from '../key/EngineKey' +import {EngineKeyInterface} from '../key/EngineKeyInterface' +import {RequestOption} from '../../imageknife/RequestOption' -export class EngineKeyFactories { - buildCacheKey( - request) { - return new EngineKey(request).generateCacheKey(); +export class EngineKeyFactories implements EngineKeyInterface { + // 生成内存缓存 + generateMemoryCacheKey(loadSrc:string,size:string,transformed:string,dontAnimate:boolean) { + return EngineKey.generateMemoryCacheKey(loadSrc,size,transformed,dontAnimate); + } + // 生成原图变换后的图片的磁盘缓存 + generateTransformedDiskCacheKey(loadSrc:string,size:string,transformed:string,dontAnimate:boolean) { + return EngineKey.generateTransformedDiskCacheKey(loadSrc,size,transformed,dontAnimate); + } + // 生成原图的磁盘缓存 + generateOriginalDiskCacheKey(loadSrc:string) { + return EngineKey.generateOriginalDiskCacheKey(loadSrc); } - buildDataKey( - request - ) { - return new EngineKey(request).generateDataKey() + public static createMemoryCacheKey(loadSrc:string,size:string,transformed:string,dontAnimate:boolean, redefineUrl?:(loadSrc:string)=>string, addOtherInfo?:string):string{ + return EngineKey.generateMemoryCacheKey(loadSrc,size,transformed,dontAnimate,redefineUrl,addOtherInfo); } - buildResourceKey( - request - ) { - return new EngineKey(request).generateResourceKey() + + public static createTransformedDiskCacheKey(loadSrc:string,size:string,transformed:string,dontAnimate:boolean, redefineUrl?:(loadSrc:string)=>string, addOtherInfo?:string):string { + return EngineKey.generateTransformedDiskCacheKey(loadSrc,size,transformed,dontAnimate,redefineUrl,addOtherInfo); } + + public static createOriginalDiskCacheKey(loadSrc:string, redefineUrl?:(loadSrc:string)=>string, addOtherInfo?:string):string { + return EngineKey.generateOriginalDiskCacheKey(loadSrc,redefineUrl,addOtherInfo); + } + + + + } diff --git a/imageknife/src/main/ets/components/cache/key/EngineKeyInterface.ets b/imageknife/src/main/ets/components/cache/key/EngineKeyInterface.ets new file mode 100644 index 0000000..8f9f051 --- /dev/null +++ b/imageknife/src/main/ets/components/cache/key/EngineKeyInterface.ets @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the 'License'); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an 'AS IS' BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import {RequestOption} from '../../imageknife/RequestOption' + +export interface EngineKeyInterface { + // 生成内存缓存 + generateMemoryCacheKey(loadSrc:string,size:string,transformed:string,dontAnimate:boolean) : string + // 生成原图变换后的图片的磁盘缓存 + generateTransformedDiskCacheKey(loadSrc:string,size:string,transformed:string,dontAnimate:boolean) : string + // 生成原图的磁盘缓存 + generateOriginalDiskCacheKey(loadSrc:string) : string +} + + + diff --git a/imageknife/src/main/ets/components/imageknife/ImageKnife.ets b/imageknife/src/main/ets/components/imageknife/ImageKnife.ets index 28de40a..862666d 100644 --- a/imageknife/src/main/ets/components/imageknife/ImageKnife.ets +++ b/imageknife/src/main/ets/components/imageknife/ImageKnife.ets @@ -16,6 +16,7 @@ import { DiskLruCache } from "@ohos/disklrucache" import { LruCache } from "../cache/LruCache" import {EngineKeyFactories} from "../cache/key/EngineKeyFactories" +import {EngineKeyInterface} from "../cache/key/EngineKeyInterface" import {RequestOption} from "../imageknife/RequestOption" import {AsyncCallback} from "../imageknife/interface/asynccallback" import {PlaceHolderManager} from "../imageknife/holder/PlaceHolderManager" @@ -60,7 +61,8 @@ export class ImageKnife { private defaultLifeCycle: IDrawLifeCycle; - + // 开发者可配置全局缓存 + private engineKeyImpl: EngineKeyInterface; private constructor(imgCtx) { this.imageKnifeContext = imgCtx; @@ -85,6 +87,8 @@ export class ImageKnife { // 通用文件格式识别初始化 this.fileTypeUtil = new FileTypeUtil(); + + this.engineKeyImpl = new EngineKeyFactories(); } getMemoryCache(): LruCache{ @@ -137,6 +141,9 @@ export class ImageKnife { this.defaultLifeCycle = viewLifeCycle; } + setEngineKeyImpl(impl:EngineKeyInterface){ + this.engineKeyImpl = impl; + } private static sInstance: ImageKnife; @@ -217,18 +224,45 @@ export class ImageKnife { let cacheKey; let transferKey; let dataKey; - factories = new EngineKeyFactories(); + if(this.engineKeyImpl){ + factories = this.engineKeyImpl; + }else { + factories = new EngineKeyFactories(); + } // 生成内存缓存key 内存 变换后磁盘 - cacheKey = factories.buildCacheKey(request); + let loadKey = ''; + if(typeof request.loadSrc == 'string'){ + loadKey = request.loadSrc; + }else{ + loadKey = JSON.stringify(request.loadSrc); + } + + let size = JSON.stringify(request.size); + + let transformed = ''; + if(request && request.transformations) { + for (let i = 0; i < request.transformations.length; i++) { + if (i == request.transformations.length - 1) { + transformed += request.transformations[i].getName() + ""; + } else { + transformed += request.transformations[i].getName() + ","; + } + } + } + + let dontAnimateFlag = request.dontAnimateFlag; + + + + + cacheKey = factories.generateMemoryCacheKey(loadKey,size,transformed,dontAnimateFlag); // 生成磁盘缓存变换后数据key 变换后数据保存在磁盘 - - transferKey = factories.buildResourceKey(request); + transferKey = factories.generateTransformedDiskCacheKey(loadKey,size,transformed,dontAnimateFlag); // 生成磁盘缓存源数据key 原始数据保存在磁盘 - - dataKey = factories.buildDataKey(request); + dataKey = factories.generateOriginalDiskCacheKey(loadKey); request.generateCacheKey = cacheKey; request.generateResourceKey = transferKey; diff --git a/package.json b/package.json index a09d904..6fb348b 100644 --- a/package.json +++ b/package.json @@ -13,8 +13,10 @@ "dependencies": { "@ohos/hypium": "1.0.3", "@ohos/hvigor-ohos-plugin": "1.4.0", + "decode-ico": "^0.4.1", "hypium": "^1.0.0", "@ohos/hvigor": "1.4.0", + "@ohos/gif-drawable": "^0.2.1", "@ohos/gpu_transform": "^0.1.0" } } From be3c4eb03a6f29f5a5bc34de0ed712522cfd74e8 Mon Sep 17 00:00:00 2001 From: zhoulisheng1 Date: Mon, 20 Mar 2023 16:27:32 +0800 Subject: [PATCH 2/2] =?UTF-8?q?1.=E6=96=B0=E5=A2=9E=E5=8A=9F=E8=83=BD:?= =?UTF-8?q?=E5=8A=A0=E8=BD=BD=E5=AA=92=E4=BD=93=E5=9B=BE=E5=BA=93=E7=9A=84?= =?UTF-8?q?uri=E5=9B=BE=E7=89=87=202.=E6=96=B0=E5=A2=9E=E6=B5=8B=E8=AF=95?= =?UTF-8?q?=E9=A1=B5=E9=9D=A2=EF=BC=8CdataShareUriLoadPage.ets=E7=94=A8?= =?UTF-8?q?=E4=BA=8E=E6=B5=8B=E8=AF=95=E5=8A=A0=E8=BD=BD=E5=AA=92=E4=BD=93?= =?UTF-8?q?=E5=9B=BE=E5=BA=93=E7=9A=84uri=E5=9B=BE=E7=89=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zhoulisheng1 --- .../src/main/ets/entryability/EntryAbility.ts | 14 +++ .../main/ets/pages/dataShareUriLoadPage.ets | 104 ++++++++++++++++++ .../ets/pages/imageknifeTestCaseIndex.ets | 5 + entry/src/main/module.json5 | 20 +++- .../resources/base/profile/main_pages.json | 3 +- .../networkmanage/DownloadClient.ets | 4 + .../networkmanage/LoadDataShareFileClient.ets | 37 +++++++ .../networkmanage/LoadLocalFileClient.ets | 2 +- 8 files changed, 186 insertions(+), 3 deletions(-) create mode 100644 entry/src/main/ets/pages/dataShareUriLoadPage.ets create mode 100644 imageknife/src/main/ets/components/imageknife/networkmanage/LoadDataShareFileClient.ets diff --git a/entry/src/main/ets/entryability/EntryAbility.ts b/entry/src/main/ets/entryability/EntryAbility.ts index 5589925..0542346 100644 --- a/entry/src/main/ets/entryability/EntryAbility.ts +++ b/entry/src/main/ets/entryability/EntryAbility.ts @@ -3,6 +3,8 @@ import hilog from '@ohos.hilog'; import window from '@ohos.window'; import { ImageKnife,ImageKnifeDrawFactory } from '@ohos/imageknife' import { CustomEngineKeyImpl } from './CustomEngineKeyImpl' +import abilityAccessCtrl,{Permissions} from '@ohos.abilityAccessCtrl'; + export default class EntryAbility extends UIAbility { onCreate(want, launchParam) { @@ -22,6 +24,18 @@ export default class EntryAbility extends UIAbility { // Main window is created, set main page for this ability hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageCreate'); + let list : Array = ['ohos.permission.MEDIA_LOCATION','ohos.permission.READ_MEDIA']; + let permissionRequestResult; + let atManager = abilityAccessCtrl.createAtManager(); + atManager.requestPermissionsFromUser(this.context, list, (err,result)=>{ + if(err){ + console.log("dodo requestPermissionsFromUserError:"+JSON.stringify(err)); + }else{ + permissionRequestResult = result; + console.log("dodo permissionRequestResult:"+JSON.stringify(permissionRequestResult)) + } + }) + windowStage.loadContent('pages/index', (err, data) => { if (err.code) { hilog.error(0x0000, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? ''); diff --git a/entry/src/main/ets/pages/dataShareUriLoadPage.ets b/entry/src/main/ets/pages/dataShareUriLoadPage.ets new file mode 100644 index 0000000..20775d4 --- /dev/null +++ b/entry/src/main/ets/pages/dataShareUriLoadPage.ets @@ -0,0 +1,104 @@ +/* + * Copyright (C) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import mediaLibrary from '@ohos.multimedia.mediaLibrary'; +import { + ImageKnifeComponent, + ImageKnifeOption, +} from '@ohos/imageknife' +import ArkWorker from '@ohos.worker' +@Entry +@Component +struct DataShareUriLoadPage { + private globalGifWorker:any = undefined + @State imageKnifeOption1: ImageKnifeOption = + { + loadSrc: $r('app.media.icon'), + + placeholderSrc: $r('app.media.icon_loading'), + errorholderSrc: $r('app.media.icon_failed') + }; + + + + build() { + Scroll() { + Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) { + Text("获取媒体图库的uri用ImageKnife展示").fontSize(15) + Flex({ direction: FlexDirection.Row, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) { + Button("点击加载Uri并展示") + .onClick(() => { + // 获取mediaLibrary实例,后续用到此实例均采用此处获取的实例 + const context = getContext(this); + let media = mediaLibrary.getMediaLibrary(context); + + let fileKeyObj = mediaLibrary.FileKey; + let imageType = mediaLibrary.MediaType.IMAGE; + // 创建文件获取选项,此处参数为获取image类型的文件资源 + let imagesFetchOp = { + selections: fileKeyObj.MEDIA_TYPE + '= ?', + selectionArgs: [imageType.toString()], + }; + // 获取文件资源,使用callback方式返回异步结果 + media.getFileAssets(imagesFetchOp, (error, fetchFileResult) => { + // 判断获取的文件资源的检索结果集是否为undefined,若为undefined则接口调用失败 + if (fetchFileResult == undefined) { + console.log('get fetchFileResult failed with error: ' + error); + return; + } + // 获取文件检索结果集中的总数 + const count = fetchFileResult.getCount(); + // 判断结果集中的数量是否小于0,小于0时表示接口调用失败 + if (count < 0) { + console.log('get count from fetchFileResult failed, count: ' + count); + return; + } + // 判断结果集中的数量是否等于0,等于0时表示接口调用成功,但是检索结果集为空,请检查文件获取选项参数配置是否有误和设备中是否存在相应文件 + if (count == 0) { + console.log('The count of fetchFileResult is zero'); + return; + } + console.log('Get fetchFileResult successfully, count: ' + count); + // 获取文件检索结果集中的第一个资源,使用callback方式返回异步结果 + fetchFileResult.getFirstObject((error, fileAsset) => { + // 检查获取的第一个资源是否为undefined,若为undefined则接口调用失败 + if (fileAsset == undefined) { + console.log('get first object failed with error: ' + error); + return; + } + console.log("fileAsset id="+fileAsset.id + " fileAsset uri="+fileAsset.uri + " fileAsset displayName="+fileAsset.displayName) + + // 加载图库第一张图片的uri + this.imageKnifeOption1 = { + loadSrc: fileAsset.uri, + placeholderSrc: $r('app.media.icon_loading'), + errorholderSrc: $r('app.media.icon_failed') + } + // 释放FetchFileResult实例并使其失效。无法调用其他方法 + fetchFileResult.close(); + }); + }); + }).margin({ top: 5, left: 3 }) + ImageKnifeComponent({ imageKnifeOption: this.imageKnifeOption1 }).width(300).height(300) + }.width('100%').backgroundColor(Color.Pink) + + + + } + } + .width('100%') + .height('100%') + } + +} \ No newline at end of file diff --git a/entry/src/main/ets/pages/imageknifeTestCaseIndex.ets b/entry/src/main/ets/pages/imageknifeTestCaseIndex.ets index f01d186..8cc6451 100644 --- a/entry/src/main/ets/pages/imageknifeTestCaseIndex.ets +++ b/entry/src/main/ets/pages/imageknifeTestCaseIndex.ets @@ -139,6 +139,11 @@ struct IndexFunctionDemo { console.log("重试Retry") router.push({ uri: "pages/frescoRetryTestCasePage" }); }).margin({ top: 5, left: 3 }) + Button("加载媒体库uri") + .onClick(() => { + console.log("加载媒体库uri") + router.push({ uri: "pages/dataShareUriLoadPage" }); + }).margin({ top: 5, left: 3 }) }.width('100%').height(60).backgroundColor(Color.Pink) Text("测试pngj和裁剪").fontSize(15) diff --git a/entry/src/main/module.json5 b/entry/src/main/module.json5 index 7071f74..f15f6f5 100644 --- a/entry/src/main/module.json5 +++ b/entry/src/main/module.json5 @@ -46,7 +46,25 @@ "name": "ohos.permission.INTERNET", "usedScene": { "abilities": [ - "FormAbility" + "EntryAbility" + ], + "when": "always" + } + }, + { + "name": "ohos.permission.MEDIA_LOCATION", + "usedScene": { + "abilities": [ + "EntryAbility" + ], + "when": "always" + } + }, + { + "name": "ohos.permission.READ_MEDIA", + "usedScene": { + "abilities": [ + "EntryAbility" ], "when": "always" } diff --git a/entry/src/main/resources/base/profile/main_pages.json b/entry/src/main/resources/base/profile/main_pages.json index 1d45314..59f4362 100644 --- a/entry/src/main/resources/base/profile/main_pages.json +++ b/entry/src/main/resources/base/profile/main_pages.json @@ -23,6 +23,7 @@ "pages/cropImagePage2", "pages/svgTestCasePage", "pages/gifTestCasePage", - "pages/imageknifeTestCaseIndex" + "pages/imageknifeTestCaseIndex", + "pages/dataShareUriLoadPage" ] } diff --git a/imageknife/src/main/ets/components/imageknife/networkmanage/DownloadClient.ets b/imageknife/src/main/ets/components/imageknife/networkmanage/DownloadClient.ets index 485f1b3..4e1589b 100644 --- a/imageknife/src/main/ets/components/imageknife/networkmanage/DownloadClient.ets +++ b/imageknife/src/main/ets/components/imageknife/networkmanage/DownloadClient.ets @@ -19,12 +19,14 @@ import { Md5 } from '../../cache/Md5' import { FileUtils } from '../../cache/FileUtils' import { NetworkDownloadClient } from './NetworkDownloadClient' import { LoadLocalFileClient } from './LoadLocalFileClient' +import { LoadDataShareFileClient } from './LoadDataShareFileClient' import loadRequest from '@ohos.request'; // 数据加载器 export class DownloadClient implements IDataFetch { private networkClient = new NetworkDownloadClient(); private localFileClient = new LoadLocalFileClient(); + private dataShareFileClient = new LoadDataShareFileClient(); loadData(request: RequestOption, onCompleteFunction, onErrorFunction) { if (typeof request.loadSrc == 'string') { @@ -32,6 +34,8 @@ export class DownloadClient implements IDataFetch { .filesDir) || request.loadSrc.startsWith(globalThis.ImageKnife.getImageKnifeContext().cacheDir)) { // 本地沙盒 this.localFileClient.loadData(request, onCompleteFunction, onErrorFunction) + }else if(request.loadSrc.startsWith('datashare://')){ + this.dataShareFileClient.loadData(request, onCompleteFunction, onErrorFunction) } else { // 网络下载 this.networkClient.loadData(request, onCompleteFunction, onErrorFunction) diff --git a/imageknife/src/main/ets/components/imageknife/networkmanage/LoadDataShareFileClient.ets b/imageknife/src/main/ets/components/imageknife/networkmanage/LoadDataShareFileClient.ets new file mode 100644 index 0000000..ba73295 --- /dev/null +++ b/imageknife/src/main/ets/components/imageknife/networkmanage/LoadDataShareFileClient.ets @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { IDataFetch } from '../networkmanage/IDataFetch' +import { RequestOption } from '../RequestOption' +import fs from '@ohos.file.fs'; + + +export class LoadDataShareFileClient implements IDataFetch { + loadData(request: RequestOption, onComplete: (img: ArrayBuffer) => void, onError: (err: string) => void) { + if (typeof request.loadSrc == 'string') { + fs.open(request.loadSrc,fs.OpenMode.READ_ONLY).then((file)=>{ + let stat = fs.statSync(file.fd); + let buf = new ArrayBuffer(stat.size); + fs.read(file.fd, buf).then((readLen)=>{ + onComplete(buf); + fs.close(file.fd); + }).catch(err=>{ + onError('LoadDataShareFileClient fs.read err happend uri='+request.loadSrc+" err.msg="+err.message+" err.code="+err.code) + }) + }).catch(err=>{ + onError('LoadDataShareFileClient fs.open err happend uri='+request.loadSrc+" err.msg="+err.message+" err.code="+err.code) + }) + } + } +} \ No newline at end of file diff --git a/imageknife/src/main/ets/components/imageknife/networkmanage/LoadLocalFileClient.ets b/imageknife/src/main/ets/components/imageknife/networkmanage/LoadLocalFileClient.ets index 4998b72..f4df6bf 100644 --- a/imageknife/src/main/ets/components/imageknife/networkmanage/LoadLocalFileClient.ets +++ b/imageknife/src/main/ets/components/imageknife/networkmanage/LoadLocalFileClient.ets @@ -19,7 +19,7 @@ import { Md5 } from '../../cache/Md5' import { FileUtils } from '../../cache/FileUtils' import loadRequest from '@ohos.request'; -export class LoadLocalFileClient { +export class LoadLocalFileClient implements IDataFetch { loadData(request: RequestOption, onComplete: (img: ArrayBuffer) => void, onError: (err: string) => void) { if (typeof request.loadSrc == 'string') { let fileBuffer = FileUtils.getInstance().readFilePic(request.loadSrc)