#夏日挑战赛# HarmonyOS - DataAbilityHelper访问文件功能 原创 精华

中软小助手
发布于 2022-6-13 17:51
浏览
4收藏

作者:贾叶照

本文正在参加星光计划3.0–夏日挑战赛

前言(Data Ability)

使用Data模板的Ability又简称Data,有助于应用管理其自身和其他应用存储数据的访问,并提供与其他应用共享数据的方法。Data既可用于同设备不同应用的数据共享,也支持跨设备不同应用的数据共享。  

数据的存放形式多样,可以是数据库,也可以是磁盘上的文件。Data对外提供对数据的增、删、改、查,以及打开文件等接口,这些接口的具体实现由开发者提供。

URI

Data的提供方和使用方都通过URI(Uniform Resource Identifier,统一资源标识符)来标识一个具体的数据,例如数据库中的某个表或磁盘上的某个文件。HarmonyOS的URI仍基于URI通用标准,格式如下:
 #夏日挑战赛# HarmonyOS - DataAbilityHelper访问文件功能-鸿蒙开发者社区
其中:

  • scheme:协议方案名,固定为“dataability”,代表Data Ability所使用的协议类型。
  • authority:设备ID。如果为跨设备场景,则为目标设备的ID;如果为本地设备场景,则不需要填写。
  • path:资源的路径信息,代表特定资源的位置信息。
  • query:查询参数。
  • fragment:可以用于指示要访问的子资源。

URI示例:

  • 跨设备场景:dataability://device_id/com.domainname.dataability.persondata/person/10
  • 本地设备:dataability:///com.domainname.dataability.persondata/person/10

说明
本地设备的“device_id”字段为空,因此在“dataability:”后面有三个“/”。

访问Data

开发者可以通过DataAbilityHelper类来访问当前应用或其他应用提供的共享数据。DataAbilityHelper作为客户端,与提供方的Data进行通信。Data接收到请求后,执行相应的处理,并返回结果。DataAbilityHelper提供了一系列与Data Ability对应的方法。  
下面介绍DataAbilityHelper具体的使用步骤。

声明使用权限

如果待访问的Data声明了访问需要权限,则访问此Data需要在配置文件中声明需要此权限。

"reqPermissions": [
    {
        "name": "com.example.dataabilityhelperdemo.DataAbility.DATA"
    }
]

如果访问的数据是文件,则还需要添加访问存储读、写的权限:ohos.permission.READ_USER_STORAGE和ohos.permission.WRITE_USER_STORAGE。

创建DataAbilityHelper

DataAbilityHelper为开发者提供了creator()方法(已过期),现在使用create()方法来创建DataAbilityHelper实例。该方法为静态方法,有多个重载。最常见的方法是通过传入一个context对象来创建DataAbilityHelper对象。

获取helper对象示例:

DataAbilityHelper helper = DataAbilityHelper.creator(this);

访问Data Ability

DataAbilityHelper为开发者提供了一系列的接口来访问不同类型的数据(文件、数据库等)。

  • 访问文件
    DataAbilityHelper为开发者提供了FileDescriptor openFile(Uri uri, String mode)方法来操作文件。此方法需要传入两个参数,其中uri用来确定目标资源路径,mode用来指定打开文件的方式,可选方式包含“r”(读), “w”(写), “rw”(读写),“wt”(覆盖写),“wa”(追加写),“rwt”(覆盖写且可读)。

该方法返回一个目标文件的FD(文件描述符),把文件描述符封装成流,开发者就可以对文件流进行自定义处理。

  • 访问数据库
    DataAbilityHelper为开发者提供了增、删、改、查以及批量处理等方法来操作数据库。

创建DataAbility

创建一个名为UserDataAbility的Data

  public class UserDataAbility extends Ability {
    private static final HiLogLabel LABEL_LOG = new HiLogLabel(3, 0xD001100, "Demo");
    @Override
    public void onStart(Intent intent) {
        super.onStart(intent);
        HiLog.info(LABEL_LOG, "UserDataAbility onStart");
    }

    @Override
    public ResultSet query(Uri uri, String[] columns, DataAbilityPredicates predicates) {
        return null;
    }

    @Override
    public int insert(Uri uri, ValuesBucket value) {
        HiLog.info(LABEL_LOG, "UserDataAbility insert");
        return 999;
    }

    @Override
    public int delete(Uri uri, DataAbilityPredicates predicates) {
        return 0;
    }

    @Override
    public int update(Uri uri, ValuesBucket value, DataAbilityPredicates predicates) {
        return 0;
    }

    @Override
    public FileDescriptor openFile(Uri uri, String mode) {
        return null;
    }

    @Override
    public String[] getFileTypes(Uri uri, String mimeTypeFilter) {
        return new String[0];
    }

    @Override
    public PacMap call(String method, String arg, PacMap extras) {
        return null;
    }

    @Override
    public String getType(Uri uri) {
        return null;
    }
}

自动生成增删改查、打开文件、获取文件类型、一个回调、获取Uri类型和一个onStart方法。
在config.json配置文件中自动添加了如下配置:

  ...
 "abilities": [
      {
        "skills": [
          {
            "entities": [
              "entity.system.home"
            ],
            "actions": [
              "action.system.home"
            ]
          }
        ],
        "orientation": "unspecified",
        "name": "com.example.dataabilityhelperdemo.MainAbility",
        "icon": "$media:icon",
        "description": "$string:mainability_description",
        "label": "$string:entry_MainAbility",
        "type": "page",
        "launchType": "standard"
      },
      {
        "permissions": [
          "com.example.dataabilityhelperdemo.DataAbilityShellProvider.PROVIDER"
        ],
        "name": "com.example.dataabilityhelperdemo.UserDataAbility",
        "icon": "$media:icon",
        "description": "$string:userdataability_description",
        "type": "data",
        "uri": "dataability://com.example.dataabilityhelperdemo.UserDataAbility"
      }
    ]

如上配置中:

  • type: 类型为data。
  • uri:对外提供的访问路径,唯一。
  • permissions:访问Data Ability时需要申请的访问权限。

关键代码:

     //初始化文件
    private void initFile() {
        //获取文件目录
        File dataDir = new File(this.getDataDir().toString());
        if(!dataDir.exists()){
            dataDir.mkdirs();
        }
        //目标文件
        targetFile = new File(Paths.get(dataDir.toString(),"name.txt").toString());
        RawFileEntry  rawFileEntry = this.getResourceManager().getRawFileEntry("resources/rawfile/name.txt");
        try {
            Resource resource = rawFileEntry.openRawFile();
            FileOutputStream  fos = new FileOutputStream(targetFile);
            byte[] buffer = new byte[4096];
            int count =0;
            while((count = resource.read(buffer)) >=0){
                fos.write(buffer,0,count);
            }
            resource.close();
            fos.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

initFile方法用于初始化文件,将源文件写入目标文件,ResourceManager类的getRawFileEntry方法,获取到RawFileEntry类,RawFileEntry类就代表rawfile目录下的文件,最后通过rawFileEntry.openRawFile()就可以获取到指定文件名的文件。在resource目录的rawfile目录下创建名为name.txt文件,内容如下:

  HarmonyOS

效果展示

 #夏日挑战赛# HarmonyOS - DataAbilityHelper访问文件功能-鸿蒙开发者社区

获取文件数据

ability_main.xml布局文件,点击按钮,显示文件里面的内容。

<?xml version="1.0" encoding="utf-8"?>
<DirectionalLayout
    xmlns:ohos="http://schemas.huawei.com/res/ohos"
    ohos:height="match_parent"
    ohos:width="match_parent"
    ohos:alignment="center"
    ohos:orientation="vertical">
    <Button
        ohos:id="$+id:button"
        ohos:height="match_content"
        ohos:width="match_parent"
        ohos:text="获取数据"
        ohos:text_size="40vp"/>
    <Text
        ohos:id="$+id:text_helloworld"
        ohos:height="match_content"
        ohos:width="match_content"
        ohos:background_element="$graphic:background_ability_main"
        ohos:layout_alignment="horizontal_center"
        ohos:text_size="40vp"
        />

</DirectionalLayout>

关键代码如下:

   public class MainAbilitySlice extends AbilitySlice {
    private Button button;
    private Text   textDesc;
    @Override
    public void onStart(Intent intent) {
        super.onStart(intent);
        super.setUIContent(ResourceTable.Layout_ability_main);
        button = (Button)findComponentById(ResourceTable.Id_button);
        textDesc = (Text)findComponentById(ResourceTable.Id_text_helloworld);
        button.setClickedListener(listener ->this.getFile());
    }

    private void getFile() {
        DataAbilityHelper helper = DataAbilityHelper.creator(this);
        Uri uri = Uri.parse("dataability:///com.example.dataabilityhelperdemo.UserDataAbility");
        try{
            FileDescriptor fileDescriptor = null;
            fileDescriptor = helper.openFile(uri,"r");
            textDesc.setText(FileUtils.getFileContent(fileDescriptor));
        }catch (DataAbilityRemoteException | IOException e){
            e.printStackTrace();
        }
    }
}

FileUtils.java

public class FileUtils {
    public static String getFileContent(FileDescriptor  fd)throws IOException{
        FileInputStream  fis = new FileInputStream(fd);
        int a=0;
        StringBuilder builder = new StringBuilder();
        while ((a= fis.read()) !=-1){
            builder.append((char) a);
        }
        fis.close();
        return builder.toString();
    }
}

源码下载地址

总结

访问文件的关键在于目标文件的文件描述符的获取,使用文件描述符封装成的文件流,进行文件操作。

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

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

©著作权归作者所有,如需转载,请注明出处,否则将追究法律责任
已于2022-6-16 10:26:25修改
6
收藏 4
回复
举报
3条回复
按时间正序
/
按时间倒序
只有敬亭山
只有敬亭山

学到了!

get 一个小知识

回复
2022-6-14 13:55:45
中软小助手
中软小助手

持续分享,努力学习

回复
2022-6-14 13:58:46
OS中的塔秋莎
OS中的塔秋莎 回复了 只有敬亭山
学到了! get 一个小知识

欢迎一起交流学习

回复
2022-6-16 10:30:00
回复
    相关推荐