安全控件-保存网络图片至相册
安全控件-保存网络图片至相册
安全控件-保存网络图片至相册
安全控件-保存网络图片至相册
概述
安全控件是系统提供的一组系统实现的ArkUI组件,应用集成这类组件就可以实现在用户点击后自动授权,而无需弹窗授权。它们可以作为一种“特殊的按钮”融入应用页面,实现用户点击即许可的设计思路。
主要优点有:
- 用户可掌握授权时机,授权范围最小化。
- 授权场景可匹配用户真实意图。
- 减少弹窗打扰。
- 开发者不必向应用市场申请权限,简化操作。
安全控件列表
目前系统提供三类安全控件:
该控件对应剪贴板读取特权。应用集成粘贴控件后,用户点击该控件,应用读取剪贴板数据时不会弹窗提示。
建议使用场景:粘贴控件可以用于任何应用需要读取剪贴板的场景,避免弹窗提示对用户造成干扰。
该控件对应媒体库写入特权。应用集成保存控件后,用户点击该控件,应用会获取10秒内访问媒体库特权接口的授权。
建议使用场景:保存控件可以用于任何应用需要保存文件到媒体库的场景(保存图片、保存视频等)。与Picker需要拉起系统应用再由用户选择具体路径保存的方式不同,保存控件将直接保存到指定媒体库路径,操作更快捷。
该控件对应精准定位特权。应用集成位置控件后,用户点击该控件,无论应用是否申请过或者被授予精准定位权限,都会在本次前台期间获得精准定位的授权,可以调用位置服务获取精准定位。
建议使用场景:应用不是强位置关联应用(如导航、运动健康等),仅在部分前台场景需要使用位置信息(如定位城市、打卡、分享位置等)。如果需要长时间使用或是在后台使用位置信息,建议申请位置权限。
使用保存控件
保存控件是一种特殊的安全控件,它允许用户通过点击按钮临时获取存储权限,而无需通过权限弹框进行授权确认。
集成保存控件后,当用户点击该控件时,应用会获得10秒内访问媒体库特权接口的授权。这适用于任何需要将文件保存到媒体库的应用场景,例如保存图片或视频等。
与需要触发系统应用并由用户选择具体保存路径的Picker不同,保存控件可以直接保存到指定的媒体库路径,使得操作更为便捷。
使用 SaveButton
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
import { http } from '@kit.NetworkKit';
import { image } from '@kit.ImageKit';
import { BusinessError } from '@kit.BasicServicesKit';
import { photoAccessHelper } from '@kit.MediaLibraryKit';
import { promptAction } from '@kit.ArkUI';
import { fileIo as fs } from '@kit.CoreFileKit';
/**
* TODO 图片相关工具类
* 1、保存网络图片
*/
export class ImageUtil {
static pixelMap: PixelMap | undefined = undefined;
// 保存网络图片
// 可以使用安全控件中的保存控件,免去权限申请和权限请求等环节,获得临时授权,保存对应图片
// 需要申请权限:ohos.permission.INTERNET
static saveImageWithUrl(url: string) {
let responseCode = http.ResponseCode;
let OutData: http.HttpResponse;
let imagePackerApi = image.createImagePacker();
let packOpts: image.PackingOption = { format: 'image/jpeg', quality: 98 };
// 确保网络正常
http.createHttp().request(url, {
method: http.RequestMethod.GET,
connectTimeout: 60000,
readTimeout: 60000
},
async (error: BusinessError, data: http.HttpResponse) => {
if (error) {
console.error(`http reqeust failed with. Code: ${error.code}, message: ${error.message}`);
} else {
OutData = data;
let code: http.ResponseCode | number = OutData.responseCode;
if (responseCode.OK === code) {
let imageData: ArrayBuffer = OutData.result as ArrayBuffer;
let imageSource: image.ImageSource = image.createImageSource(imageData);
class tmp {
height: number = 100
width: number = 100
};
let options: Record<string, number | boolean | tmp> = {
'alphaType': 0, // 透明度
'editable': false, // 是否可编辑
'pixelFormat': 3, // 像素格式
'scaleMode': 1, // 缩略值
'size': { height: 100, width: 100 }
}; // 创建图片大小
imageSource.createPixelMap(options).then((pixelMap: PixelMap) => {
ImageUtil.pixelMap = pixelMap;
ImageUtil.pixelMap.getImageInfo().then((info: image.ImageInfo) => {
console.info('info.width = ' + info.size.width);
}).catch((err: BusinessError) => {
console.error('Failed ' + err);
})
imagePackerApi.packing(pixelMap, packOpts).then(async (buffer: ArrayBuffer) => {
try {
const context = getContext();
let helper = photoAccessHelper.getPhotoAccessHelper(context);
let uri = await helper.createAsset(photoAccessHelper.PhotoType.IMAGE, 'png');
let file = await fs.open(uri, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE);
// 写入文件
await fs.write(file.fd, buffer);
promptAction.showToast({ message: '已保存至相册!' });
// 关闭文件
await fs.close(file.fd);
} catch (error) {
console.error('error is ' + JSON.stringify(error));
}
}).catch((error: BusinessError) => {
console.error('Failed to pack the image. And the error is: ' + error);
})
pixelMap.release();
})
}
}
}
)
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
Row() {
Image(params.qrData)
.width('240lpx')
.height('240lpx')
.margin({ right: '20lpx' })
Column() {
Text('点击下方按钮保存二维码')
.TextExtend()
Text('打开微信,扫一扫进行关注')
.TextExtend()
SaveButton({
icon: SaveIconStyle.LINES,
text: SaveDescription.SAVE_IMAGE
})
.onClick(async (event: ClickEvent, result: SaveButtonOnClickResult) => {
if (result === SaveButtonOnClickResult.SUCCESS) {
ImageUtil.saveImageWithUrl(params.qrData)
} else {
Toast.show('设置权限失败');
}
})
}
.alignItems(HorizontalAlign.Start)
}
本文由作者按照 CC BY 4.0 进行授权