HarmonyOS - 本地相册的纠葛

Posted OpenHarmony技术社区

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HarmonyOS - 本地相册的纠葛相关的知识,希望对你有一定的参考价值。

作者:庄茂裕

前言:

二月再见,三月你好,阳春三月万物复苏,愿一切美好都如约而至。携手共创,鸿蒙社区。前几天有个同事问我如何把图片存在系统相册的图片,当时我就懵逼了,鸿蒙的好像真的不怎么懂?而且这个操作在我们平时开发时也经常用到,所以搞起。

效果展示

HarmonyOS

踩坑之路

1.应该官网有介绍吧,去官网看看,发现是有一丢丢介绍

附上链接:

​https://developer.harmonyos.com/cn/docs/documentation/doc-guides/media-data-mgmt-storage-0000001050994909​

2.都说安卓和鸿蒙差不多,应该思路是差不多的吧,于是找到一片文章(​​https://harmonyos.51cto.com/posts/10568​​)里面有MediaStore类,用于操作系统媒体数据库的类,鸿蒙确实也有个类似的类AVStorage,但是现在开放的功能不如MediaStore强大。

3.后面发现是鸿蒙的设计思路有点像ios的,每个应用的都有独自沙河目录,每个app的数据都存储在当前的应用当中,这样大大的确保数据的隐蔽性和安全性,这样比安卓安全性好很多。

保存图片到系统相册

demo布局:

//展示图片
<Image
ohos:id="$+id:show_photo"
ohos:
ohos:
ohos:image_src="$media:empty"
ohos:scale_mode="zoom_center"
ohos:top_margin="30fp"
/>

//选择图片
<Text
ohos:id="$+id:select_photo"
ohos:
ohos:
ohos:background_element="$graphic:background_ability_main"
ohos:layout_alignment="horizontal_center"
ohos:text="选择图片"
ohos:text_size="20vp"
ohos:top_margin="10fp"
/>

//保存图片
<Text
ohos:top_margin="10fp"
ohos:id="$+id:save_photo"
ohos:
ohos:
ohos:background_element="$graphic:background_ability_main"
ohos:layout_alignment="horizontal_center"
ohos:text="保存图片"
ohos:text_size="20vp"
/>

效果如图:

HarmonyOS

涉及权限

权限

描述

ohos.permission.WRITE_USER_STORAGE

写文件权限。

ohos.permission.READ_USER_STORAGE

读文件权限

config.json权限配置如下:

"reqPermissions": [
"name": "ohos.permission.READ_USER_STORAGE",
"name": "ohos.permission.WRITE_USER_STORAGE"
]

动态申请权限

需要动态申请这两个权限,申请时会有权限弹窗,不写的话,不会有权限弹窗,但是也是可以使用的。

String[] permissions = "ohos.permission.READ_USER_STORAGE", "ohos.permission.WRITE_USER_STORAGE";
requestPermissionsFromUser(permissions, 0);

保存图片

获取到权限之后,就可以保存图片到系统相册了,我们媒体的增删改查都需要用到DataAbilityHelper和AVStorage。

//保存图片到相册 fileName文件名  PixelMap 图片数据
private void saveImageToLibrary(String fileName, PixelMap pixelMap)
try
ValuesBucket valuesBucket = new ValuesBucket();
//文件名
valuesBucket.putString(AVStorage.Images.Media.DISPLAY_NAME, fileName);
//相对路径
valuesBucket.putString("relative_path", "DCIM/");
//文件格式,类型要一定要注意要是JPEG,PNG类型不支持
valuesBucket.putString(AVStorage.Images.Media.MIME_TYPE, "image/JPEG");
//应用独占:is_pending设置为1时表示只有该应用能访问此图片,其他应用无法发现该图片,当图片处理操作完成后再吧is_pending设置为0,解除独占,让其他应用可见
valuesBucket.putInteger("is_pending", 1);

//鸿蒙的helper.insert方法和安卓的contentResolver.insert方法有所不同,安卓方法直接返回一个uri,我们就可以拿来直接操作,而鸿蒙方法返回官方描述是Returns the index of the inserted data record(返回插入的数据记录的索引),这个index我的理解就是id,因此,我们需要自己在后面拼出文件的uri再进行操作
DataAbilityHelper helper = DataAbilityHelper.creator(this);
int index = helper.insert(AVStorage.Images.Media.EXTERNAL_DATA_ABILITY_URI, valuesBucket);
Uri uri = Uri.appendEncodedPathToUri(AVStorage.Images.Media.EXTERNAL_DATA_ABILITY_URI, String.valueOf(index));

//获取到uri后,安卓通过contentResolver.openOutputStream(uri)就能获取到输出流来写文件,而鸿蒙没有提供这样的方法,我们就只能通过uri获取FileDescriptor,再通过FileDescriptor生成输出流打包编码成新的图片文件,这里helper.openFile方法一定要有“w”写模式,不然会报FileNotFound的错误。
FileDescriptor fd = helper.openFile(uri, "w");
ImagePacker imagePacker = ImagePacker.create();
ImagePacker.PackingOptions packingOptions = new ImagePacker.PackingOptions();
OutputStream outputStream = new FileOutputStream(fd);
packingOptions.format = "image/jpeg";
packingOptions.quality = 90;
boolean result = imagePacker.initializePacking(outputStream, packingOptions);
if (result)
result = imagePacker.addImage(pixelMap);
if (result)
long dataSize = imagePacker.finalizePacking();


outputStream.flush();
outputStream.close();
valuesBucket.clear();
//解除独占
valuesBucket.putInteger("is_pending", 0);
helper.update(uri, valuesBucket, null);
catch (Exception e)
e.printStackTrace();

效果如下

HarmonyOS

读取本地相册图片

在config.json中配置读取文件权限(ohos.permission.READ_USER_STORAGE)

"reqPermissions": ["name": "ohos.permission.READ_USER_STORAGE"]

在ability中手动申请权限

String[] permissions = "ohos.permission.READ_USER_STORAGE";
requestPermissionsFromUser(permissions, 0);

弹出数据来源选择框,获取数据来源的方式。

//选择图片
private void selectPhoto()
//调起系统的选择来源数据视图
Intent intent = new Intent();
Operation opt=new Intent.OperationBuilder().withAction("android.intent.action.GET_CONTENT").build();
intent.setOperation(opt);
intent.addFlags(Intent.FLAG_NOT_OHOS_COMPONENT);
intent.setType("image/*");
startAbilityForResult(intent, imgRequestCode);

效果如图:

HarmonyOS

下面是选择图片的回调,imgRequestCode字段的是自定义的,必须是int的类型,这个字段是和上面的selectPhoto()方法里面的imgRequestCode是一致的,根据这个imgRequestCode来判断是否从选择图片的回调回来的,

/*选择图片回调*/
@Override
protected void onAbilityResult(int requestCode, int resultCode, Intent resultData)
if(requestCode==imgRequestCode && resultData!=null)

//选择的Img对应的Uri
String chooseImgUrl=resultData.getUriString();
//定义数据能力帮助对象
DataAbilityHelper helper=DataAbilityHelper.creator(getContext());
//定义图片来源对象
ImageSource imageSource = null;
//获取选择的Img对应的Id
String chooseImgId=null;
//如果是选择文件则getUriString结果为dataability:///com.android.providers.media.documents/document/image%3A437,其中%3A437是":"的URL编码结果,后面的数字就是image对应的Id
//如果选择的是图库则getUriString结果为dataability:///media/external/images/media/262,最后就是image对应的Id
//这里需要判断是选择了文件还是图库
if(chooseImgUri.lastIndexOf("%3A")!=-1)
chooseImgId = chooseImgUri.substring(chooseImgUri.lastIndexOf("%3A")+3);

else
chooseImgId = chooseImgUri.substring(chooseImgUri.lastIndexOf(/)+1);

//获取图片对应的uri,由于获取到的前缀是content,我们替换成对应的dataability前缀
Uri uri=Uri.appendEncodedPathToUri(AVStorage.Images.Media.EXTERNAL_DATA_ABILITY_URI,chooseImgId);
try
//读取图片
FileDescriptor fd = helper.openFile(uri, "r");
imageSource = ImageSource.create(fd, null);
//创建位图
PixelMap pixelMap = imageSource.createPixelmap(null);
//设置图片控件对应的位图
photo.setPixelMap(pixelMap);
catch (Exception e)
e.printStackTrace();
finally
if (imageSource != null)
imageSource.release();



总结

官网现有文档不多,开发鸿蒙的时候遇到很多问题,有安卓基础的小伙伴可以参考安卓的思路去解决,应该可以事半功倍,希望本次分享对大家有所帮助。


更多原创内容请关注:​​中软国际 HarmonyOS 技术团队​

入门到精通、技巧到案例,系统化分享HarmonyOS开发技术,欢迎投稿和订阅,让我们一起携手前行共建鸿蒙生态。


​想了解更多关于鸿蒙的内容,请访问:​

​51CTO和华为官方合作共建的鸿蒙技术社区​

​https://ost.51cto.com/#bkwz​

HarmonyOS

以上是关于HarmonyOS - 本地相册的纠葛的主要内容,如果未能解决你的问题,请参考以下文章

两个下拉框的纠葛

生成器与for循环的纠葛

ZipInputStream和RSA算法的纠葛

DOM事件与jQuery事件的是非纠葛

Oracle Linux和Redhat 啥纠葛

Linux系统进程的知识总结,进程与线程之间的纠葛...